home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1994…tember: Reference Library / Dev.CD Sep 94.toast / Technical Documentation / Mac Tech Notes (DocViewer) / Printing / TN-Printing / TN-Printing
Encoding:
Text File  |  1994-07-24  |  961.0 KB  |  2,165 lines  |  [ONLN/HLX2]

  1. PR 1 - Color Printing
  2. Printing    
  3. Revised by:    Scott "ZZ" Zimmerman    January 1988
  4.             March 1988
  5. Written by:    Ginger Jernigan    February 1986
  6. This discusses color printing in a Macintosh application.
  7. Whereas the original eight-color model of QuickDraw was sufficient for printing in color on the ImageWriter II, the introduction of Color QuickDraw has created the need for more sophisticated printing methods.
  8. The first section describes using the eight-color QuickDraw model with the ImageWriter II and ImageWriter LQ drivers. Since the current Print Manager does not support Color GrafPorts, the eight-color model is the only method available for the ImageWriters.
  9. The next section describes a technique that can be used for printing halftone images using PostScript (when it is available). Also described is a device independent technique for sending the PostScript data. This technique can be used on any LaserWriter driver 3.0 or later. It will work with all LaserWriters except the the LaserWriter IISC.
  10. It is very likely that better color support will be added to the Print Manager in the future. Until then, these are the best methods available.
  11. Part 1, ImageWriters
  12. The ImageWriter drivers are capable of generating each of the eight standard colors defined in QuickDraw by the following constants:
  13.     whiteColor
  14.     blackColor
  15.     redColor
  16.     greenColor
  17.     blueColor
  18.     cyanColor
  19.     magentaColor
  20.     yellowColor
  21. To generate color all you need to do is set the foreground and background colors before you begin drawing (initially they are set to blackColor foreground and whiteColor background). To do this you call the QuickDraw routines ForeColor and BackColor as described in Inside Macintosh. If you are using QuickDraw pictures, make sure you set the foreground and background colors before you call ClosePicture so that they are recorded in the picture. Setting the colors before calling DrawPicture doesn’t work.
  22. The drivers also recognize two of the transfer modes: srcCopy and srcOr. The effect of the other transfer modes is not well defined and has not been tested. It may be best to stay away from them.
  23. Caveats
  24. When printing a large area of more than one color you will encounter a problem with the ribbon. When you print a large area of one color, the printer’s pins pick up the color from the back of the ribbon. When another large area of color is printed, the pins deposit the previous color onto the back of the ribbon. Eventually the first color will come through to the front of the ribbon, contaminating the second color. You can get the same kind of effect if you set, for example, a foreground color of yellow and a background color of blue. The ribbon will pick up the blue as it tries to print yellow on top of it. This problem is partially alleviated in the 2.3 version of the ImageWriter driver by using a different printing technique.
  25. The ribbon goes through the printer rather quickly when printing large areas. When the ribbon comes through the second time the colors don’t look too great.
  26. Part 2, LaserWriters
  27. Using the PostScript ‘image’ Operator to Print Halftones
  28. About ‘image’
  29. The PostScript image operator is used to send Bitmaps or Pixmaps to the LaserWriter. The image operator can handle depths from 1 to 8 bits per pixel. Our current LaserWriters can only image about twenty shades of gray, but the printed page will look like there’s more. Being that the image operator is still a PostScript operator, it expects its data in the form of hexidecimal bytes. The bytes are represented by two ASCII characters(0-9,A-F). The image operator takes these parameters:
  30.     width  height  depth  matrix  image-data
  31. The first three are the width, height, and depth of the image, and the matrix is the transformation matrix to be applied to the current matrix. See the PostScript Language Reference Manual for more information. The image data is where the actual hex data should go. Instead of inserting the data between the first parameters and the image operator itself, it is better to use a small, PostScript procedure to read the data starting from right after the image operator. For example:
  32.     640 480 8 [640 0 0 480 0 0]
  33.     {currentfile picstr readhexstring pop}
  34.     image
  35.     FF 00 FF 00 FF 00 FF 00 ...
  36. In the above example, the width of the image is 640, the height is 480, and the depth is 8. The matrix (enclosed in brackets) is setup to draw the image starting at QuickDraw’s 0,0 (top left of page), and with no scaling. The PostScript code (enclosed in braces) is not executed. Instead, it is passed to the image operator, and the image operator will call it repeatedly until it has enough data to draw the image. In this case, it will be expecting 640*480 bytes. When the image operator calls the procedure, it does the following:
  37. 1.    Pushes the current file which in this case is the stream of data coming to the LaserWriter over AppleTalk. This is the first parameter to readhexstring.
  38. 2.    Next picstr is pushed. picstr is a string variable defined to hold one row of hex data. The PostScript to create the picstr is:
  39.         /picstr 640 def
  40. 3.    Now readhexstring is called to fill picstr with data from the current file. It begins reading bytes which are the characters following the image operator.
  41. 4.    Since readhexstring leaves both the string we want, and a boolean that we don’t want on the stack, we do one pop to kill of the boolean. Now the string is left behind for the image operator to use.
  42. So using the above PostScript code you can easily print an image. Just fill in the width height and depth, and send the hex data immediately following the PostScript code.
  43. Setting Up for ‘image’
  44. Most of the users of this technique are going to want to print a Color QuickDraw PixMap. Although the image command does a lot of the work for you, there are still a couple of tricks that are recommended for performance.
  45. Assume the Maximum Depth
  46. Since the current version of the image operator has a maximum depth of 8 bits/pixel, it is wise to convert the source image to the same depth before imaging. This can be done very simply by using an offscreen GrafPort that is set to 8 bits/pixel, and then using CopyBits to do the depth conversion for you. This will do a nice job of converting lower resolution images to 8 bits/pixel.
  47. Build a Color Table
  48. An 8 bit deep image can only use 256 colors. Since the image that you are starting with is probably color, and the image you get will be grayscale, you need to convert the colors in the source color table into PostScript grayscale values. This is actually easy to do using the Color Manager. First create a table that can hold 512 bytes. This is 2 bytes for each color value from 0 to 255. Since PostScript wants the values in ASCII, you need two characters for each pixel. Now loop through the colors in the color table. Call Index2Color to get the real RGB color for that index, and then call RGB2HSL to convert the RGB color into a luminance value. This value will be expressed as a SmallFract which can then be scaled into a value from 0 to 255. This value should then be converted to ASCII, and stored at the appropriate location in the table. When you are done, you should be able to use a pixel value as an index into your table of PostScript color values. For each pixel in the image, send two characters to the LaserWriter.
  49. Sending the Data
  50. Once you have set up the color table, all that left to do is to loop through all of the pixels, and send their PostScript representation to the LaserWriter. There are a couple of ways to do this. First is to use the low-level Print Manager interface and stream the PostScript using the stdBuf PrCtlCall. Although this seems like it would be the fastest way, the latest version of the LaserWriter driver (5.0) converts all low-level calls to their high level equivalent before executing them. Because of this, the low-level interface is no longer faster than the high level. In an FKEY I have written, I use the high-level Print Manager interface, and send the data via the PostScriptHandle PicComment. This way, I can buffer a large amount of data, before actually sending it. Using this technique, I have been able to image a Mac II screen in about 5 minutes on a LaserWriter Plus, and about 1.5 minutes on a LaserWriter II NTX.
  51. Further Reference:
  52. •    QuickDraw
  53. •    The Printing Manager
  54. •    PostScript Language Reference Manual, Adobe Systems
  55. PR 2 - Device-Independent Printing
  56. Printing    
  57. Revised by:        March 1988
  58. Written by:    Ginger Jernigan     May 1987
  59. The Printing Manager was designed to give Macintosh applications a device- independent method of printing, but we have provided device-dependent information, such as the contents of the print record. Due to the large number of printer-type drivers becoming available (even for non-printer devices) device independence is more necessary than ever. What this means to you, as a developer, is that we will no longer be providing (or supporting) information regarding the internal structure of the print record. 
  60. We realize that there are situations where the application may know the best method for printing a particular document and may want to bypass our dialogs. Unfortunately, using your own dialogs or not using the dialogs at all, requires setting the necessary fields in the print record yourself. There are a number of problems:
  61. •    Many of the fields in the print record are undocumented, and, as we change the internal architecture of the Printing Manager to accommodate new devices, those undocumented fields are likely to change.
  62. •    Each driver uses the private, and many of the public, fields in the print record differently.  The implications are that you would need intimate knowledge of how each field is used by  each available driver, and you would have to set the fields in the record differently depending on the driver chosen. As the number of available printer-type drivers increases, this can become a cumbersome task.
  63. Summary
  64. To be compatible with future printer-like devices, it is essential that your application print in a device-independent manner. Avoid testing undocumented fields, setting fields in the print record directly and bypassing the existing print dialogs. Use the Printing Manager dialogs, PrintDefault and PrValidate to set up the print record for you.
  65. Further Reference:
  66. •    The Printing Manager
  67. PR 3 - Document Names and the Printing Manager
  68. Printing    
  69. Revised by:        March 1988
  70. Written by:    Bryan Stearns    July 1987
  71. Our compatibility testing for LaserShare (Apple’s LaserWriter spooler) has turned up a number of applications that do not provide the Printing Manager with a document name; although this feature is not required, it is nice for users that share printers.
  72. Some printers (usually those that are shared between many users, like the LaserWriter) can provide the names of the users who are printing and the documents that are being printed to others interested in using the printer. 
  73. If the chosen printer uses a document name, the Printing Manager gets the name from the frontmost window’s title. If there is no front window, or if the window’s title is empty, the Printing Manager defaults to “unknown.”
  74. This method was chosen because it works most transparently to applications; however, it won’t work if your application doesn’t display windows when printing (for instance, many applications that use windows for their documents do not open their documents when printing in response to a Finder “Print” command).
  75. As a general solution to this problem, you can put up a window containing a message like “Press –. to cancel printing”, and give it the document’s title. If the window  is one that doesn’t have a title bar (like dBoxProc), this title will not be displayed. MacApp takes this approach. If for some reason you don’t want to put up a visible window, you can create a tiny window and hide it behind the menu bar: for instance, global coordinates of (1,1,2,2). Make sure you use a plainDBox, so that no title will be drawn (otherwise, in the unlikely case that a user is using a Macintosh II with two stacked screens, main screen on the bottom, the title might be visible on the upper screen).
  76. Since the Printing Manager checks the name at PrValidate time, call PrValidate after PrCloseDoc and before the next PrOpenDoc, if you want unique names. 
  77. A number of applications set the document name in the print record directly. You should not do this because a) not all printers support this field, and b) none are guaranteed to support it in the future. (Apple does not guarantee that internal fields of the Printing Manager’s data structures will remain the same; the Printing Manager is targeted for substantial internal change!)
  78. Further Reference:
  79. •    The Printing Manager
  80. •    Technical Note M.IM.DevIndPrinting— Device-Independent Printing
  81. PR 4 - LaserWriter Optimization Techniques
  82. Printing    
  83. Revised by:    Pete “Luke” Alexander    October 1990
  84. Written by:    Ginger Jernigan    February 1986
  85. This Technical Note discusses techniques for optimizing code for printing on the LaserWriter.
  86. Changes since March 1988:  Updated the “Printable Paper Area” and “Memory Considerations” sections as well as the printer IDs, moved the error messages from the end of the Note to Technical Note #161, A Printing Loop That Cares…, and removed the “Spool-A-Page/Print-A-Page” section because Technical Note #125, Effect of Spool-A-Page/Print-A-Page on Shared Printers, already thoroughly covers this topic.
  87. Introduction
  88. Although the Printing Manager was originally designed to allow application code to be printer independent, there are some things about the LaserWriter that, in some cases, have to be addressed in a printer dependent way.  This Note describes what the LaserWriter can and cannot do, memory considerations, speed considerations, as well as other things you need to watch out for if you want to make your printing more efficient on the LaserWriter.
  89. How To Determine The Currently Selected Printer
  90. With the addition of new picture comments and the PrGeneral procedure, an application should never need to know the type of device to which it is connected.  However, some developers feel their application should be able to take advantage of all of the features provided by a particular device, not just those provided by the Printing Manager, and in doing so, these developers produce device-dependent applications, which can produce unpredictable results third-party and new Apple printing devices.  For this reason, Apple strongly recommends that you use only the features provided by the Printing Manager, and do not try to use unsupported device features.
  91. Even though there is no supported method for determining a device’s type, there is one method described in the original Inside Macintosh that still works for ImageWriter and LaserWriter printer drivers.  This method is not supported, meaning that at some point in the future it will no longer work.  If you use this method in your application, it is up to you to weigh the value of the feature against the compatibility risk.  The following method works for all ImageWriter, ImageWriter II, and LaserWriter (original, Plus, IInt, IIntx) drivers.  Since all new devices released from Apple and third-party developers have their own unique ID, it is up to you to decide what to do with an ID that your application does not recognize.
  92. If you are using the high-level Printing Manager interface, first call PrValidate to make sure you have the correct print record.  Look at the high byte of the wdev word in the TPrStl subrecord of the print record.  Note that if you have your own driver and want to have your own number, please let DTS know, and DTS can register it.
  93. Following is the current list of printer IDs:
  94. Printer    wDev
  95. ImageWriter I, ImageWriter II    1
  96. LaserWriter, LaserWriter Plus, Laser-
  97. Writer IInt, LaserWriter IIntx, and
  98. Personal LaserWriter nt    3
  99. LaserWriter IIsc, Personal LaserWriter sc    4
  100. ImageWriter LQ    5
  101. If you are using the low-level Printing Manager interface, there is no dependable way of getting the wDev information.  You should not attempt to determine the device ID when using the low-level Printing Manager interface.
  102. Using QuickDraw With the LaserWriter
  103. When you print to the LaserWriter, all of the QuickDraw calls you make are translated (via QuickDraw bottlenecks) into PostScript®, which is in the LaserWriter ROM.  Most of the operations available in QuickDraw are available in PostScript, with a few exceptions.  The LaserWriter driver does not support the following:
  104. •    XOR and NotXOR transfer modes.
  105. •    The grafverb invert.
  106. •    _SetOrigin calls within PrOpenPage and PrClosePage calls.  Use _OffsetRect instead.  (This is fixed in version 3.0 and later of the driver.)
  107. •    Regions are ignored.  You can simulate regions using polygons or bitmaps.  Refer to Technical Note #41, Drawing Into An Off-Screen Bitmap, for how to create off-screen bitmaps.
  108. •    Clip regions should be limited to rectangles.
  109. •    There is a small difference in character widths between screen fonts and printer fonts.  Only the end points of text strings are the same.
  110. What You See Is Not Always What You Get
  111. Unfortunately, what you see on the screen is not always what you get.  If you are using standard graphic objects, like rectangles, circles, etc., the object is the same size on the LaserWriter as it is on the screen.  There are, however, two types of objects where this is not the case:  text and bitmaps.
  112. The earlier noted difference between the widths of characters on the screen and the widths of characters on the printer is due to the difference in resolution.  However, to maintain the integrity of line breaks, the driver changes the word and character spacing to maintain the end points of the lines as specified.  What this all means is that you cannot count on the positions or the widths of printed characters being exactly the same as they are on the screen.  This is why in the original MacDraw®, for example, if one carefully places text and a rectangle and prints it, the text sometimes extends beyond the bounds of the rectangle on the printed page.  If an application does its own line layout (i.e., positions the words on the line itself), then it may want to disable the LaserWriter’s line layout routines.  To disable these routines, use the LineLayoutOff picture comment described in the LaserWriter Reference Manual and Technical Note #91, Optimizing for the LaserWriter—Picture Comments.
  113. The sole exception to this rule is if an application is running on 128K ROMs or later.  The 128K ROM Font Manager supports the specification of fractional pixel widths for screen fonts, increasing the screen to printer accuracy.  This fractional width feature is disabled by default.  To enable it, an application  can use _SetFractEnable, after calling _InitFonts.
  114. Applications can use picture comments to left-, right-, or center-justify text.  Only the left, right, or center end points are accurate.  If the text is fully justified, both end points are accurate.  Technical Note #91, Optimizing for the LaserWriter—Picture Comments, discusses these picture comments.
  115. Memory Considerations
  116. To print to the LaserWriter, you need to make sure that you have enough memory available to load the driver’s code.  The best way to do this is to have all the code you need for printing in a separate segment and unload everything else.  When you print to the LaserWriter you are only able to print in Draft mode.  You are not able to spool (as the ImageWriter does in the standard or high-quality settings), and your print code, data, and the driver code have to be resident in memory.
  117. In terms of memory requirements, there is not any magic number that always works with all printer drivers (including third-party printer drivers) that are available for the Macintosh.  To make sure there is enough memory available during print time, you should make your printing code a separate segment and swap out all unwanted code and data before you call _PrOpen.
  118. Printable Paper Area
  119. On the LaserWriter there is a 0.45-inch border that surrounds the printable area of the paper (this is assuming an 8.5” x 11” paper).  If you select the “Larger Print Area” option in the Page Setup dialog box, the border changes to 0.25 of an inch.  This printable area is different than the available print area of the ImageWriter.  An application cannot print a larger area because of the memory PostScript needs to image a page.  PostScript takes the amount of memory available in the printer and centers it on the paper, and there is not enough RAM in the LaserWriter to image an entire sheet of paper.
  120. Page Sizes
  121. Many developers have expressed a desire to support page sizes other than those provided by the Apple printer drivers.  Even though some devices can physically support other page sizes, there is no way for an application to tell the driver to use this size.  With the ImageWriter driver, it is possible to modify certain fields in the print record and expand the printable area of the page.  However, each of the Apple drivers implements the page sizes in a different way.  No one method works for all drivers.  Because of this difference, it is strongly recommended that applications do not attempt to change the page sizes provided in the “Style” dialog box.  If your application currently supports page sizes other than those provided by the printer driver, you are taking a serious compatibility risk with future Apple and third-party printer drivers.
  122. Speed Considerations
  123. Although the LaserWriter is relatively fast, there are some techniques an application can use to ensure its maximum performance.
  124. •    Try to avoid using the QuickDraw Erase calls (e.g., _EraseRect, _EraseOval, etc.).  It takes a lot of time to handle the erase function because every bit (90,000 bits per square inch) has to be cleared.  Erasing is unnecessary because the paper does not need to be erased the way the screen does.
  125. •    Printing patterns takes time, since the bitmap for the pattern has to be built.  The patterns black, white, and all the gray patterns have been optimized to use the PostScript gray scales.  If you use a different pattern it works, but it just takes longer than usual.  In addition, the patterns in driver version 3.0 are rotated; they are not rotated in version 1.0.
  126. •    Try to avoid frequently changing fonts.  PostScript has to build each character it needs either by using the drawing commands for the built-in LaserWriter fonts or by resizing bitmaps downloaded from screen fonts on the Macintosh.  As each character is built, it is cached (if there’s room), so if that character is needed again PostScript gets if from the cache.  When the font changes, the characters have to be built from scratch in the new font, which takes time.  If the font is not in the LaserWriter, it takes time to download it from the Macintosh.  If the user has the option of choosing fonts, you have no control over this variable; however, if you  control which fonts to use, keep this in mind.
  127. •    Avoid using _TextBox.  It makes calls to _EraseRect, which slows the printer, for every line of text it draws.  You might want to use a different method of displaying text (e.g., _DrawString or _DrawText) or write your own version of _TextBox.  If an application is currently calling _TextBox, changing to another method of displaying text can improve speed on the order of five to one.
  128. •    Because of the way rectangle intersections are determined, if your clip region falls outside of the rPage rectangle, you slow down the printer substantially.  By making sure your clip region is entirely within the rPage rectangle, you can get a speed improvement of approximately four to one.
  129. •    Do not use spool-a-page/print-a-page as some applications do when printing on the ImageWriter.  It slows things down considerably because of all of the preparation that has to be done when a job is initiated.  Refer to Technical Note #125, Effect of Spool-A-Page/Print-A-Page on Shared Printers, for more information.
  130. •    Using _DrawChar to place every character to print can take a lot of time.  One reason, of course, is because it has to go through the bottlenecks for every character that is drawn.  The other is that the printer driver does its best to do line layout, making the character spacing just right.  If you are trying to position characters and the driver is trying to position characters too, there is conflict, and printing takes much longer than necessary.  In version 3.0 of the driver, there are picture comments that turn off the line layout optimization, alleviating some of the problem.  Refer to Technical Note #91, Optimizing for the LaserWriter—Picture Comments, for more information.
  131. Clipping Within Text Strings
  132. When clipping characters out of a string, make sure that the clipping rectangle or region is greater than the bounding box of the text you want to clip.  The reason is that if you clip part of a character (e.g., a descender), the clipped character has to be rebuilt, which takes time.  In addition, because of the difference between screen fonts and printer fonts, chances are that you cannot accurately clip the right characters unless you are running on the 128K ROMs and have fractional pixel widths enabled.
  133. When to Validate the Print Record
  134. To validate the print record, call PrValidate.  You need validation to check to see if all of the fields are accurate according to the current printer selected and the current version of the driver.  You should call PrValidate when you have allocated a new print record or whenever you need to access information from the print record (i.e., when you get rPage).  The routines PrStlDialog and PrJobDialog call PrValidate when they are called, so you do not have to worry about it if you use these calls.
  135. Empty QuickDraw Objects
  136. QuickDraw objects that are empty (i.e., they have no pixels in them) and are filled but not framed, do not print on the ImageWriter and do not show up on the screen; however, on the LaserWriter they are real objects and do print.
  137. Further Reference:
  138. •    Inside Macintosh, Volume I, QuickDraw
  139. •    Inside Macintosh, Volume II, The Printing Manager
  140. •    LaserWriter Reference Manual
  141. •    Technical Note M.IM.OffscreenBitMap—
  142.          Drawing Into An Off-Screen Bitmap
  143. •    Technical Note M.IM.PictComments —
  144.          Optimizing for the LaserWriter—Picture Comments
  145. •    Technical Note M.IM.Spooler —
  146.          Effect of Spool-A-Page/Print-A-Page on Shared Printers
  147. •    Technical Note M.IM.PrintLoop —
  148.          A Printing Loop That Cares…
  149. •    PostScript Language Reference, Adobe Systems, Incorporated
  150. •    PostScript Language Tutorial and Cookbook, Adobe Systems, Incorporated
  151. MacDraw is a registered trademark of Claris Corporation.
  152. PostScript is a registered trademark of Adobe Systems, Incorporated.
  153. PR 5 - LaserWriter ROMs Bugs
  154. Printing    
  155. Revised by:    Ginger Jernigan    July 1987
  156. Updated:        March 1988
  157. Written by:    Ginger Jernigan    May 1987
  158. These are LaserWriter bugs that your users may encounter when printing from any Macintosh application. These are for your information; you cannot code around them. The bugs described here occur in the 1.0 and 2.0 LaserWriter ROMs.
  159. To determine which ROMs their LaserWriter contains, users can look at the test page that the LaserWriter prints at start-up time. In addition to other information (detailed in the LaserWriter user’s manual), the ROM version is shown at the bottom of the line graph. The original LaserWriter contained version 1.0 ROMs. The currently shipping LaserWriter and those upgraded to the LaserWriter Plus contain version 2.0 ROMs.
  160. These are some of the problems we know of:
  161. 1.    If the level of paper in the paper tray is getting low, and the user prints a document that will cause the tray to become empty, a PostScript error may occur. This problem exists in both the 1.0 and 2.0 LaserWriter ROMs and will not be fixed in the next ROM version.
  162. 2.    If a user prints more than 15 copies of a document, a timeout condition may occur causing the print job to abort. With LaserShare, this problem can occur with as few as 9 copies. This problem is a result of the LaserWriter turning AppleTalk off while it is printing. It doesn’t send out any packets to tell the world it’s still alive while it is printing, so the connection times out after about 2 minutes. This problem exists in both the 1.0 and 2.0 LaserWriter ROMs and will not be fixed in the next ROM version.
  163. 3.    When printing a document that contains more than 10 patterns, users may receive intermittent PostScript errors. This usually occurs when trying to print a lot of patterns, and a bitmap image on the same page. The code for imaging patterns allocates almost all of the available RAM for itself, so when the bitmap imaging code tries to allocate space, and there isn’t enough (and it doesn’t know how to reclaim memory from the previous operation), a limitcheck error occurs. This problem exists in 2.0 LaserWriter ROMs. It will be improved but not fixed in the next ROM version.
  164. 4.    If a user chooses US Letter or B5 paper and has a different sized tray in the printer, and prints using manual feed, the LaserWriter will print assuming that the paper being fed manually is the same size as that in the tray. For example, if they have a US letter tray in the LaserWriter and print a document formatted for B5 letter using manual feed, the image will not be centered on the page. The printer assumes that the manually fed paper is also US letter size and prints the image positioned accordingly, despite the driver’s instructions. This is a bug in the Note operator in PostScript, which the driver uses for specifying the US letter and B5 letter paper sizes. The workaround is to tell the user to put an B5 tray in the printer when printing B5 manually. This problem exists in the 1.0 and 2.0 ROMs and will not be fixed in the next ROM version. 
  165. By the way, an interesting, but annoying, occurance of this bug happens when manually printing Legal sized documents with the 4.0 LaserWriter driver. When the Larger Print Area option in the style dialog is deselected (which is the default) the driver uses the Note operator to specify the page size. When the user prints the document using manual feed, and has a US letter tray in the printer, the image is shifted up on the page cutting off the top of the image. If you tell the user to turn on the Larger Print Area option in the style dialog, the driver specifies the page size using Legal instead of Note and the image is printed properly.
  166. Further Reference:
  167. •    The Printing Manager
  168. •    PostScript Language Reference Manual, Adobe Systems
  169. PR 6 - Using Low-Level Printing Calls With AppleTalk ImageWriters
  170. Printing    
  171. Revised by:    Scott "ZZ" Zimmerman    February 1988
  172. Revised by:        March 1988
  173. Written by:    Ginger Jernigan     May 1987
  174. When you use the low-level printer driver to print, you don’t get the benefits of the error checking that is done when you use the high-level Printing Manager. So, if the user prints to an AppleTalk ImageWriter (including an AppleTalk ImageWriter LQ) that is busy printing another job, the driver doesn’t know whether the printer is busy, offline, or disconnected.  Because of this, PrError will return (and PrintErr will contain) abortErr.
  175. Since there is no way to tell when you are printing to an AppleTalk ImageWriter, the only workaround for this is to use high-level Printing Manager interface.
  176. Further Reference:
  177. •    The Printing Manager
  178. PR 7 - PrGeneral
  179. Printing    
  180. Revised by:        March 1988
  181. Written by:    Ginger Jenigan    May 1987
  182. The Printing Manager architecture has been expanded to include a new procedure called PrGeneral. The features described here are advanced, special-purpose features, intended to solve specific problems for those applications that need them. The calls to determine printer resolution introduce a good deal of complexity into the application’s code, and should be used only when necessary.
  183. Version 2.5 (and later) of the ImageWriter driver and version 4.0 (and later) of the LaserWriter driver implement a generic Printing Manager procedure called PrGeneral. This procedure allows the Print Manager to expand in functionality, by allowing printer drivers to implement various new functions. The Pascal declaration of PrGeneral is:
  184.     PROCEDURE PrGeneral (pData: Ptr);
  185. The pData parameter is a pointer to a data block. The structure of the data block is declared as follows:
  186.     TGnlData = RECORD {1st 8 bytes are common for all PrGeneral calls)
  187.        iOpCode   : INTEGER;  {input}
  188.        iError    : INTEGER;  {output}
  189.        lReserved : LONGINT;  {reserved for future use}
  190.        {more fields here, depending on particular call}
  191.     END;
  192. The first field is a 2-byte opcode, iOpCode, which acts like a routine selector. The currently available opcodes are described below.
  193. The second field is the error result, iError, which is returned by the print code. This error only reflects error conditions that occur during the PrGeneral call. For example, if you use an opcode that isn’t implemented in a particular printer driver then you will get a OpNotImpl error.
  194. Here are the errors currently defined:
  195.     CONST    
  196.        noErr = 0;                 {everything’s hunky}
  197.        NoSuchRsl = 1;             {the resolution you chose isn’t available}
  198.        OpNotImpl = 2;             {the driver doesn’t support this opcode}
  199. After calling PrGeneral you should always check PrError. If noErr is returned, then you can proceed. If ResNotFound is returned, then the current printer driver doesn’t support PrGeneral and you should proceed appropriately. See Technical Note #118 for details on checking errors returned by the Printing Manager. 
  200. IError is followed by a four byte reserved field (that means don’t use it). The contents of the rest of the data block depends on the opcode that the application uses. There are currently five opcodes used by the ImageWriter and LaserWriter drivers.
  201. The Opcodes
  202. Initially, the following calls are implemented via PrGeneral:
  203.     •  GetRslData (get resolution data): iOpCode = 4
  204.     •  SetRsl (set resolution): iOpCode = 5
  205.     •  DraftBits (bitmaps in draft mode): iOpCode = 6
  206.     •  noDraftBits (no bitmaps in draft mode): iOpCode = 7
  207.     •  GetRotn (get rotation): iOpCode = 8
  208. The GetRslData and SetRsl allow the application to find out what physical resolutions the printer supports, and then specify a supported resolution. DraftBits and noDraftBits invoke a new feature of the ImageWriter, allowing bitmaps (imaged via CopyBits) to be printed in draft mode. GetRotn lets an application know whether landscape has been selected. Below is a detailed description of how each routine works.
  209. The GetRslData Call
  210. GetRslData (iOpCode = 4) returns a record that lets the application know what resolutions are supported by the current printer. The application can then use SetRsl (description follows) to tell the printer driver which one it will use. This is the format of the input data block for the GetRslData call:
  211.     TRslRg = RECORD    {used in TGetRslBlk}
  212.         {0 if printer only supports discrete resolutions}
  213.         iMin, iMax:    Integer;
  214.     END;
  215.     TRslRec = RECORD    {used in TGetRslBlk}
  216.         iXRsl, iYRsl: Integer; {a discrete, physical resolution}
  217.     END;
  218.     TGetRslBlk = RECORD    {data block for GetRslData call}
  219.         iOpCode:    Integer;    {input; = getRslDataOp}
  220.         iError:    Integer;    {output}
  221.         lReserved:    LongInt;    {reserved for future use}
  222.         iRgType:    Integer;    {output; version number}
  223.         XRslRg:    TRslRg;    {output; range of X resolutions}
  224.         YRslRg:    TRslRg;    {output; range of Y resolutions}
  225.         iRslRecCnt:    Integer;    {output; how many RslRecs follow}
  226.         rgRslRec:    ARRAY[1..27] OF TRslRec;  {output; number filled depends on
  227.                                                        printer type}
  228.     END;
  229. The iRgType field is much like a version number; it determines the interpretation of the data that follows. At present, a iRgType value of 1 applies both to the LaserWriter and to the ImageWriter.
  230. For variable-resolution printers like the LaserWriter, the resolution range fields XRslRg and YRslRg express the ranges of values to which the X and Y resolutions can be set. For discrete-resolution printers like the ImageWriter, the values in the resolution range fields are zero.
  231. Note: In general, X and Y in these records are the horizontal and vertical directions of the printer, not the document! In landscape orientation, X is horizontal on the printer but vertical on the document.
  232. After the resolution range information there is a word which gives the number of resolution records that contain information. These records indicate the physical resolutions at which the printer can actually print dots. Each resolution record gives an X value and a Y value.
  233. When you call PrGeneral you pass in a data block that looks like this:
  234. Below is the data block returned for the LaserWriter:
  235. Note that all the resolution range numbers happen to be the same for this printer. There is only one resolution record, which gives the physical X and Y resolutions of the printer (300x300).
  236. Below is the data block returned for the ImageWriter.
  237. All the resolution range values are zero, because only discrete resolutions can be specified for this printer. There are four resolution records giving these discrete physical resolutions.
  238. Note that GetRslData always returns the same information for a particular printer type—it is not dependent on what the user does or on printer configuration information. 
  239. The SetRsl Call
  240. SetRsl (iOpCode = 5) is used to specify the desired imaging resolution, after using GetRslData to determine a workable pair of values. Below is the format of the data block:
  241.     TSetRslBlk =    RECORD    {data block for SetRsl call}
  242.         iOpCode:    Integer;    {input; = setRslOp}
  243.         iError:    Integer;    {output}
  244.         lReserved:    LongInt;    {reserved for future use}
  245.         hPrint:    THPrint;    {input; handle to a valid print record}
  246.         iXRsl:    Integer;    {input; desired X resolution}
  247.         iYRsl:    Integer;    {input; desired Y resolution}
  248.     END;
  249. hPrint should be the handle of a print record that has previously been passed to PrValidate. If the call executes successfully, the print record is updated with the new resolution; the data block comes back with 0 for the error and is otherwise unchanged.
  250. However, if the desired resolution is not supported, the error is set to noSuchRsl and the resolution fields are set to the printer’s default resolution
  251. Note that you can undo the effect of a previous call to SetRsl by making another call that specifies an unsupported resolution (such as 0x0), forcing the default resolution.
  252. The DraftBits Call
  253. DraftBits (iOpCode = 6) is implemented on both the ImageWriter and the LaserWriter. (On the LaserWriter it does nothing, since the LaserWriter is always in draft mode and can always print bitmaps.) Below is the format of the data block:
  254.     TDftBitsBlk =    RECORD    {data block for DraftBits and NoDraftBits calls}
  255.         iOpCode:    Integer;    {input; = draftBitsOp or noDraftBitsOp}
  256.         iError:    Integer;    {output}
  257.         lReserved:    LongInt;    {reserved for future use}
  258.         hPrint:    THPrint;    {input; handle to a valid print record}
  259.     END;
  260. hPrint should be the handle of a print record that has previously been passed to PrValidate.
  261. This call forces draft-mode (i.e., immediate) printing, and will allow bitmaps to be printed via CopyBits calls. The virtue of this is that you avoid spooling large masses of bitmap data onto the disk, and you also get better performance.
  262. The following restrictions apply:
  263. •    This call should be made before bringing up the print dialogs because it affects their appearance. On the ImageWriter, calling DraftBits disables the landscape icon in the  Style dialog, and the Best, Faster, and Draft buttons in the Job dialog.
  264. •    If the printer does not support draft mode, already prints bitmaps in draft mode, or does not  print bitmaps at all, this call does nothing.
  265. •    Only text and bitmaps can be printed.
  266. •    As in the normal draft mode, landscape format is not allowed.
  267. •    Everything on the page must be strictly Y-sorted, i.e. no reverse paper motion between one string or bitmap and the next. Note that this means you can’t have two or more objects (text or bitmaps) side by side; the top boundary of each object must be no higher than the bottom of the preceding object.
  268. The last restriction is important. If you violate it, you will not like the results. But note that if you want two or more bitmaps side by side, you can combine them into one before calling CopyBits to print the result. Similarly, if you are just printing bitmaps you can rotate them yourself to achieve landscape printing.
  269. The NoDraftBits Call
  270. NoDraftBits (iOpCode = 7) is implemented on both the ImageWriter and the LaserWriter. (On the LaserWriter it does nothing, since the LaserWriter is always in draft mode and can always print bitmaps.) The format of the data block is the same as that for the DraftBits call.
  271. This call cancels the effect of any preceding DraftBits call. If there was no preceding DraftBits call, or the printer does not support draft-mode printing anyway, this call does nothing.
  272. The GetRotn Call
  273. GetRotn (iOpCode = 8) is implemented on the ImageWriter and LaserWriter. Here is the format of the data block:
  274.     TGetRotnBlk =    RECORD    {data block for GetRotn call}
  275.         iOpCode:    Integer;    {input; = getRotnOp}
  276.         iError:    Integer;    {output}
  277.         lReserved:    LongInt;    {reserved for future use}
  278.         hPrint:    THPrint;    {input; handle to a valid print record}
  279.         fLandscape:    Boolean;    {output; Boolean flag}
  280.         bXtra:    SignedByte;        {reserved}
  281.     END;
  282. hPrint should be the handle to a print record that has previously been passed to PrValidate.
  283. If landscape orientation is selected in the print record, then fLandscape is true.
  284. How To Use The PrGeneral Opcodes
  285. The SetRsl and DraftBits calls may require the print code to suppress certain options in the Style and/or Job dialogs, therefore they should always be called before any call to the Style or Job dialogs. An application might use these calls as follows:
  286. •    Get a new print record by calling PrintDefault, or take an existing one from a document and call PrValidate on it.
  287. •    Call GetRslData to find out what the printer is capable of, and decide what resolution to  use. Check PrError to be sure the PrGeneral call is supported on  this version of the  print code; if the error is ResNotFound, you have older print code and must print  accordingly. But if the PrError return is 0, proceed:
  288. •    Call SetRsl with the print record and the desired resolution if you wish.
  289. •    Call DraftBits to invoke the printing of bitmaps in draft mode if you wish.
  290. Note that if you call either SetRsl or DraftBits, you should do so before the user sees either of the printing dialogs.
  291. Further Reference:
  292. •    The Printing Manager
  293. PR 8 - PrGeneral Bug
  294. Printing    
  295. Revised by:        March 1988
  296. Written by:    Scott "ZZ" Zimmerman    November 1987
  297. This technical note documents a bug in the implementation of the PrGeneral procedure in the LaserWriter driver version 4.0. The bug has to do with the format of the information returned by the GetRslData opcode. This technical note will also describe a workaround for the problem.
  298. One of the opcodes supported by the PrGeneral procedure (Technical Note #128) is named GetRslData. The GetRslData operation initializes a resolution record that is of the following form:
  299.     TRslRg = RECORD {used in TGetRslBlk}
  300.         iMin:    Integer;    {0 if printer only supports discrete resolutions}
  301.         iMax:    Integer;    {0 if printer only supports discrete 
  302.                                      resolutions}
  303.     END;
  304.                         
  305.     TRslRec = RECORD    {used in TGetRslBlk}
  306.         iXRsl:    Integer;    {a discrete, physical X resolution}
  307.         iYRsl:    Integer;    {a discrete, physical Y resolution}
  308.     END;
  309.     
  310.     TGetRslBlk = RECORD {data block for GetRslData call}
  311.         iOpCode:    Integer;    {input; = getRslDataOp}
  312.         iError:     Integer;    {output}
  313.         lReserved:    LongInt;    {reserved for future use}
  314.         iRgType:    Integer;    {output; this declaration is for RgType1}
  315.         XRslRg:     TRslRg;     {output; range of X resolutions}
  316.         YRslRg:     TRslRg;     {output; range of Y resolutions}
  317.         iRslRecCnt: Integer;    {output; how many RslRecs follow}
  318.         rgRslRec:    ARRAY[1..27] 
  319.                 OF TRslRec; {output; number used depends on printer type}
  320.     END;
  321. The LaserWriter 4.0 implementation has a bug that affects the YRslRg and XRslRg fields of the TGetRslBlk record. The correct values for the fields are:
  322.         TGetRslBlk.XRslRg.iMin := 25;
  323.         TGetRslBlk.XRslRg.iMax := 1500;
  324.         TGetRslBlk.YRslRg.iMin := 25;
  325.         TGetRslBlk.YRslRg.iMax := 1500;
  326. Unfortunately, the information returned by the LaserWriter 4.0 version of PrGeneral is:
  327.         TGetRslBlk.XRslRg.iMin := 25;
  328.         TGetRslBlk.XRslRg.iMax := 25; 
  329.         TGetRslBlk.YRslRg.iMin := 1500;
  330.         TGetRslBlk.YRslRg.iMax := 1500;
  331. The recommended workaround for this problem is to use the PrDrvrVers function (Inside Macintosh II-163) to find out which version of the print driver you are using. If you are using 4.0, modify the resolution data before using it. The following code fragment illustrates this workaround:
  332.     PROCEDURE CheckRslRecord(VAR theRslRecord: TGetRslBlk);
  333.     CONST
  334.         BogusDriver = 40;
  335.     BEGIN
  336.         IF PrDrvrVers = BogusDriver THEN BEGIN
  337.             theRslRecord.XRslRg.iMax := theRslRecord.YRslRg.iMax;
  338.             theRslRecord.YRslRg.iMin := theRslRecord.XRslRg.iMin;
  339.         END;        
  340.     END;
  341. When the bug is fixed in a future version of the driver, the CheckRslRecord procedure will no longer have any effect on the resolution record. This will make sure your application gets the correct resolution data no matter which version of the driver is being used.
  342. Further Reference:
  343. •    The Print Manager
  344. •    Technical Note M.IM.PrGeneral—
  345.         PrGeneral
  346. PR 9 - Print Dialogs: Adding Items
  347. Printing    
  348. Revised by:        March 1988
  349. Written by:    Ginger Jernigan    November 1986
  350.         Lew Rollins    
  351. This technical note discusses how to add your own items to the Printing Manager’s dialogs.
  352. When the Printing Manager was initially designed, great care was taken to make the interface to the printer drivers as generic as possible in order to allow applications to print without being device-specific. There are times, however, when this type of non-specific interface interferes with the flexibility of an application. An application may require additional information before printing which is not part of the general Printing Manager interface. This technical note describes a method that an application can use to add its own items to the existing style and job dialogs.
  353. Before continuing, you need to be aware of some guidelines that will increase your chances of being compatible with the printing architecture in the future:
  354. •    Only add items to the dialogs as described in this technical note. Any other methods will decrease your chances of survival in the future.
  355. •    Do not change the position of any item in the current dialogs. This means don’t delete items from the existing item list or add items in the middle. Add items only at the end of the list.
  356. •    Don’t count on an item retaining its current position in the list. If you depend on the Draft button being a particular number in the ImageWriter’s style dialog item list, and we change the Draft button’s item number for some reason, your program may no longer function correctly.
  357. •    Don’t use more than half the screen height for your items. Apple reserves the right to expand the items in the standard print dialogs to fill the top half of the screen.
  358. •    If you are adding lots of items to the dialogs (which may confuse users), you should consider having your own separate dialog in addition to the existing Printing Manager dialogs.
  359. The Heart
  360. Before we talk about how the dialogs work, you need to know this: at the heart of the printer dialogs is a little-known data structure partially documented in the MacPrint interface file. It’s a record called TPrDlg and it looks like this:
  361.     TPrDlg = RECORD   {Print Dialog: The Dialog Stream object.}
  362.        dlg       : DialogRecord;   {dialog window}
  363.        pFltrProc : ProcPtr;        {filter proc.}
  364.        pItemProc : ProcPtr;        {item evaluating proc.}
  365.        hPrintUsr : THPrint;        {user’s print record.}
  366.        fDoIt     : BOOLEAN;
  367.        fDone     : BOOLEAN;
  368.        lUser1    : LONGINT;        {four longs reserved by Apple}
  369.        lUser2    : LONGINT;
  370.        lUser3    : LONGINT;
  371.        lUser4    : LONGINT;
  372.        iNumFst   : INTEGER;        {numeric edit items for std filter}
  373.        iNumLst   : INTEGER;      
  374.     {... plus more stuff needed by the particular printing dialog.}
  375.     END;
  376.     TPPrDlg = ^TPrDlg;             {== a dialog ptr}
  377. All of the information pertaining to a print dialog is kept in the TPrDlg record. This record will be referred to frequently in the discussion below.
  378. How the Dialogs Work
  379. When your application calls PrStlDialog and PrJobDialog, the printer driver actually calls a routine called PrDlgMain. This function is declared as follows:
  380.     FUNCTION PrDlgMain (hprint: THPrint; pDlgInit: ProcPtr): BOOLEAN;
  381. PrDlgMain first calls the pDlgInit routine to set up the appropriate dialog (in Dlg), dialog hook (pItemProc) and dialog event filter (pFilterProc) in the TPrDlg record (shown above). For the job dialog, the address of PrJobInit is passed to PrDlgMain. For the style dialog, the address of PrStlInit is passed. These routines are declared as follows:
  382.     FUNCTION PrJobInit (hPrint: THPrint): TPPrDlg;
  383.     FUNCTION PrStlInit (hPrint: THPrint): TPPrDlg;
  384. After the initialization routine sets up the TPrDlg record, PrDlgMain calls ShowWindow (the window is initially invisible), then it calls ModalDialog, using the dialog event filter pointed to by the pFltrProc field. When an item is hit, the routine pointed to by the pItemProc field is called and the items are handled appropriately. When the OK button is hit (this includes pressing Return or Enter) the print record is validated. The print record is not validated if the Cancel button is hit.
  385. How to Add Your Own Items
  386. To modify the print dialogs, you need to change the TPrDlg record before the dialog is drawn on the screen. You can add your own items to the item list, replace the addresses of the standard dialog hook and event filter with the addresses of your own routines and then let the dialog code continue on its merry way. 
  387. TPrDlg record for you and return a pointer to that record. Then call PrDlgMain directly, passing in the address of your own initialization function. The example code’s initialization function adds items to the dialog item list, saves the address of the standard dialog hook (in our global variable prPItemProc) and puts the address of our dialog hook into the pItemProc field of the TPrDlg record. Please note that your dialog hook must call the standard dialog hook to handle all of the standard dialog’s items.
  388. Note: If you wish to have an event filter, handle it the same way that you do a dialog hook.
  389. Now, here is an example (written in MPW Pascal) that modifies the job dialog. The same code works for the style dialog if you globally replace ‘Job’ with ‘Stl’. Also included is a function (AppendDITL) provided by Lew Rollins (originally written in C, translated for this technical note to MPW Pascal) which demonstrates a method of adding items to the item list, placing them in an appropriate place, and expanding the dialog window’s rectangle.
  390. The MPW Pascal Example Program
  391. PROGRAM ModifyDialogs;
  392.     USES
  393.         {$LOAD PasDump.dump}
  394.         MemTypes,QuickDraw,OSIntf,ToolIntf,PackIntf,MacPrint;
  395.     CONST
  396.         MyDITL         = 256;
  397.         MyDFirstBox  = 1;          {Item number of first box in DITL}
  398.         MyDSecondBox = 2;
  399.     VAR
  400.         PrtJobDialog: TPPrDlg;    { pointer to job dialog }
  401.         hPrintRec    : THPrint;    { Handle to print record }
  402.         FirstBoxValue,         { value of first additional box }
  403.         SecondBoxValue: Integer;     { value of second addtl. box }
  404.         prFirstItem,            { save our first item here }
  405.         prPItemProc : LongInt;    { need to store old itemProc here }
  406.         itemType     : Integer;    { need for GetDItem/SetDItem calls }
  407.         itemH         : Handle;
  408.         itemBox        : Rect;
  409.         err            : OSErr;
  410. {------------------------------------------------------------------------}
  411.     PROCEDURE _DataInit;
  412.         EXTERNAL;
  413. {------------------------------------------------------------------------}
  414.     PROCEDURE CallItemHandler(theDialog: DialogPtr; theItem: Integer;
  415.                     theProc: LongInt);
  416.         INLINE $205F            { MOVE.L (A7)+,A0}
  417.         ,$4E90;            { JSR (A0) }
  418. { this code pops off theProc and then does a JSR to it, which puts the
  419.  real return address on the stack. }
  420. {------------------------------------------------------------------------}
  421.     FUNCTION AppendDITL(theDialog: DialogPtr; theDITLID: Integer): Integer;
  422.     { version 0.1 9/11/86 Lew Rollins of Human-Systems Interface Group}
  423.     { this routine still needs some error checking }
  424. { This routine appends all of the items of a specified DITL
  425. onto the end of a specified DLOG — We don’t even need to know the format
  426. of the DLOG }
  427. { this will be done in 3 steps:
  428.  1. append the items of the specified DITL onto the existing DLOG
  429.  2. expand the original dialog window as required
  430.  3. return the adjusted number of the first new user item
  431. }
  432.     TYPE
  433.         DITLItem = RECORD    { First, a single item }
  434.             { Handle or procedure pointer for this item }
  435.                 itmHndl: Handle;
  436.             { Display rectangle for this item }
  437.                 itmRect: Rect; 
  438.             { Item type for this item — 1 byte }
  439.                 itmType: SignedByte;
  440.             { Length byte of data }
  441.                 itmData: ARRAY [0..0] OF SignedByte;
  442.         END;    {DITLItem}
  443.         pDITLItem     = ^DITLItem;
  444.         hDITLItem     = ^pDITLItem;
  445.         ItemList = RECORD    { Then, the list of items }
  446.              { Number of items minus 1 }
  447.                 dlgMaxIndex: Integer;
  448.             { Array of items }
  449.                 DITLItems: ARRAY [0..0] OF DITLItem;            END;     {ItemList}
  450.         pItemList     = ^ItemList;
  451.         hItemList     = ^pItemList;
  452.         IntPtr         = ^Integer;
  453.     VAR
  454.         offset : Point;    { Used to offset rectangles appended items}
  455.         maxRect: Rect;    { Used to track increases in window size }
  456.         hDITL : hItemList;     { Handle to DITL being appended }
  457.         pItem : pDITLItem;    { Pointer to current item being appended }
  458.         hItems: hItemList;    { Handle to DLOG’s item list }
  459.         firstItem: Integer;    { offset to first item is to be appended }
  460.         newItems: Integer;    { Count of new items }
  461.         dataSize : Integer;    { Size of data for current item }
  462.         i : Integer;         { Working index }
  463.         USB: RECORD        { needed because itmData[0] is unsigned}
  464.             CASE Integer OF
  465.                 1:
  466.                     (SBArray: ARRAY [0..1] OF SignedByte);
  467.                 2:
  468.                     (Int: Integer);
  469.         END;     {USB}
  470.     BEGIN         {AppendDITL}
  471. {
  472. Using the original DLOG
  473.  1. Remember the original window Size.
  474.  2. Set the offset Point to be the bottom of the original window.
  475.  3. Subtract 5 pixels from bottom and right, to be added
  476.       back later after we have possibly expanded window.
  477.  4. Get working Handle to original item list.
  478.  5. Calculate our first item number to be returned to caller.
  479.  6. Get locked Handle to DITL to be appended.
  480.  7. Calculate count of new items.
  481. }
  482.         maxRect := DialogPeek(theDialog)^.window.port.portRect;
  483.         offset.v := maxRect.bottom;
  484.         offset.h := 0;
  485.         maxRect.bottom := maxRect.bottom - 5;
  486.         maxRect.right := maxRect.right - 5;
  487.         hItems := hItemList(DialogPeek(theDialog)^.items);
  488.         firstItem := hItems^^.dlgMaxIndex + 2;
  489.         hDITL := hItemList(GetResource('DITL',theDITLID));
  490.         HLock(Handle(hDITL));
  491.         newItems := hDITL^^.dlgMaxIndex + 1;
  492. {
  493.  For each item,
  494.   1. Offset the rectangle to follow the original window.
  495.   2. Make the original window larger if necessary.
  496.   3. fill in item Handle according to type.
  497. }
  498.         pItem := @hDITL^^.DITLItems;
  499.         FOR i := 1 TO newItems DO BEGIN
  500.             OffsetRect(pItem^.itmRect,offset.h,offset.v);
  501.             UnionRect(pItem^.itmRect,maxRect,maxRect);
  502.             USB.Int := 0;         {zero things out}
  503.             USB.SBArray[1] := pItem^.itmData[0];
  504.             { Strip enable bit since it doesn’t matter here. }
  505.             WITH pItem^ DO
  506.                 CASE BAND(itmType,$7F) OF
  507.                     { Can’t do anything with user items. }
  508.                     userItem:     
  509.                         itmHndl := NIL;
  510.                         ctrlItem + btnCtrl,ctrlItem +                             chkCtrl,ctrlItem + radCtrl:{build                             Control)
  511.                             itmHndl := Handle(NewControl(theDialog, { theWindow }
  512.                                                                   itmRect, { boundsRect }
  513.                                                                   StringPtr(@itmData[0])^, { title }
  514.                                                                   true, { visible }
  515.                                                                   0,0,1, { value, min, max }
  516.                                                                   BAND(itmType,$03), { procID }
  517.                                                                   0)); { refCon }
  518.                         ctrlItem + resCtrl: BEGIN { Get resource                         based Control }
  519.                             itmHndl := Handle(GetNewControl(IntPtr(@itmData[1])^, { controlID }
  520.                                                                       theDialog)); { theWindow }
  521.                             ControlHandle(itmHndl)^^.contrlRect := itmRect; {give it the right
  522.                                                                                              rectangle}
  523.                             {An actionProc for a Control                              should be installed here}
  524.                         END;             {Case ctrlItem +                                       resCtrl}
  525.                         statText,editText: { Both need Handle to                                        a copy of their                                     text. }
  526.                             err := PtrToHand(@itmData[1],                             ( Start of data }
  527.                                                   itmHndl, { Address of new Handle }
  528.                                                   USB.Int); { Length of text }
  529.                         iconItem:     { Icon needs resource                                    Handle. }
  530.                             pItem^.itmHndl := GetIcon(IntPtr(@itmData[1])^); { ICON resID }
  531.                         picItem:      { Picture needs resource                                    Handle. }
  532.                             pItem^.itmHndl := Handle(GetPicture(IntPtr(@itmData[1])^));{PICT resID}
  533.                         OTHERWISE
  534.                             itmHndl := NIL;
  535.                     END;                 {Case}
  536.                 dataSize := BAND(USB.Int + 1,$FFFE);
  537.                 {now advance to next item}
  538.                 pItem := pDITLItem(Ptr(ord4(@pItem^) + dataSize +                 sizeof(DITLItem)));
  539.             END;                         {for}
  540.             err := PtrAndHand
  541.              (@hDITL^^.DITLItems,Handle(hItems),GetHandleSize(Handle(hDITL)));
  542.             hItems^^.dlgMaxIndex := hItems^^.dlgMaxIndex + newItems;
  543.             HUnlock(Handle(hDITL));
  544.             ReleaseResource(Handle(hDITL));
  545.             maxRect.bottom := maxRect.bottom + 5;
  546.             maxRect.right := maxRect.right + 5;
  547.             SizeWindow(theDialog,maxRect.right,maxRect.bottom,true);
  548.             AppendDITL := firstItem;
  549.         END;                             {AppendDITL}
  550.     {------------------------------------------------------------------------}
  551.     PROCEDURE MyJobItems(theDialog: DialogPtr; itemNo: Integer);
  552.  { 
  553.  This routine replaces the routine in the pItemProc field in the
  554.     TPPrDlg record.  The steps it takes are:
  555.     1. Check to see if the item hit was one of ours. This is done by “localizing”
  556.           the number, assuming that our items are numbered from 0..n
  557.     2. If it’s one of ours  then case it and Handle appropriately
  558.     3. If it isn’t one of ours then call the old item handler
  559.  }
  560.         VAR
  561.             MyItem,firstItem: Integer;
  562.             thePt         : Point;
  563.             thePart        : Integer;
  564.             theValue     : Integer;
  565.             debugPart    : Integer;
  566.         BEGIN                          {MyJobItems}
  567.             firstItem := prFirstItem; { remember, we saved this in                                    myJobDlgInit }
  568.             MyItem := itemNo - firstItem + 1; { “localize” current item No }
  569.             IF MyItem > 0 THEN BEGIN { if localized item > 0, it’s one of                               ours }
  570.                 { find out which of our items was hit }
  571.                 GetDItem(theDialog,itemNo,itemType,itemH,itemBox);
  572.                 CASE MyItem OF
  573.                     MyDFirstBox: BEGIN
  574.                         { invert value of FirstBoxValue and                            redraw it }
  575.                         FirstBoxValue := 1 - FirstBoxValue;
  576.                         SetCtlValue(ControlHandle(itemH),FirstBoxValue);
  577.                     END;                 {case MyDFirstBox}
  578.                     MyDSecondBox: BEGIN
  579.                         { invert value of SecondBoxValue and                           redraw it }
  580.                         SecondBoxValue := 1 - SecondBoxValue;
  581.                         SetCtlValue(ControlHandle(itemH),SecondBoxValue);
  582.                     END;                 {case                                           MyDSecondBox}
  583.                     OTHERWISE
  584.                         Debug;         { OH OH — We got an item                                       we didn’t expect }
  585.                 END;                     {Case}
  586.             END                         { if MyItem > 0 }
  587.             ELSE                  { chain to standard item handler,                                whose address is saved                                                                         in prPItemProc }
  588.                 CallItemHandler(theDialog,itemNo,prPItemProc);
  589.         END;                             { MyJobItems }
  590.     {------------------------------------------------------------------------}
  591.     FUNCTION MyJobDlgInit(hPrint: THPrint): TPPrDlg;
  592. {
  593.  This routine appends items to the standard job dialog and sets up the
  594.  user fields of the printing dialog record TPRDlg
  595.  This routine will be called by PrDlgMain
  596.  This is what it does:
  597.  1. First call PrJobInit to fill in the TPPrDlg record.
  598.  2. Append our items onto the old DITL. Set them up appropriately.
  599.  3. Save the address of the old item handler and replace it with ours.
  600.  4. Return the Fixed dialog to PrDlgMain.
  601.  }
  602.         VAR
  603.             firstItem    : Integer; { first new item number }
  604.         BEGIN                          {MyJobDlgInit}
  605.             firstItem := AppendDITL(DialogPtr(PrtJobDialog),MyDITL); 
  606.             prFirstItem := firstItem; { save this so MyJobItems can
  607.                                find it }
  608.             { now we’ll set up our DITL items — The "First Box" }
  609.             GetDItem(DialogPtr(PrtJobDialog),firstItem,itemType,itemH,itemBox);
  610.             SetCtlValue(ControlHandle(itemH),FirstBoxValue);
  611.             { now we’ll set up the second of our DITL items — The "Second               Box" }
  612.             GetDItem(DialogPtr(PrtJobDialog),firstItem +                     1,itemType,itemH,itemBox);
  613.             SetCtlValue(ControlHandle(itemH),SecondBoxValue);
  614. { Now comes the part where we patch in our item handler.  We have to save
  615.  the old item handler address, so we can call it if one of the standard
  616.  items is hit, and put our item handler’s address
  617.  in pItemProc field of the TPrDlg struct}
  618.             prPItemProc := LongInt(PrtJobDialog^.pItemProc);
  619.             { Now we’ll tell the modal item handler where our routine is }
  620.             PrtJobDialog^.pItemProc := ProcPtr(@MyJobItems);
  621.             { PrDlgMain expects a pointer to the modified dialog to be               returned.... }
  622.             MyJobDlgInit := PrtJobDialog;
  623.         END;                             {myJobDlgInit}
  624.     {------------------------------------------------------------------------}
  625.     FUNCTION Print: OSErr;
  626.         VAR
  627.             bool            : BOOLEAN;
  628.         BEGIN                          {Print}
  629.             hPrintRec := THPrint(NewHandle(sizeof(TPrint)));
  630.             PrintDefault(hPrintRec);
  631.             bool := PrValidate(hPrintRec);
  632.             IF (PrError <> noErr) THEN BEGIN
  633.                 Print := PrError;
  634.                 Exit(Print);
  635.             END;                         {If}
  636.             { call PrJobInit to get pointer to the invisible job dialog }
  637.             PrtJobDialog := PrJobInit(hPrintRec);
  638.             IF (PrError <> noErr) THEN BEGIN
  639.                 Print := PrError;
  640.                 Exit(Print);
  641.             END;                         {If}
  642.  {Here’s the line that does it all!}
  643.             IF NOT (PrDlgMain(hPrintRec,@MyJobDlgInit)) THEN BEGIN
  644.                 Print := cancel;
  645.                 Exit(Print);
  646.             END;                         {If}
  647.             IF PrError <> noErr THEN Print := PrError;
  648.             { that’s all for now }
  649.         END;                             { Print }
  650.     {------------------------------------------------------------------------}
  651.     BEGIN                              {PROGRAM}
  652.         UnloadSeg(@_DataInit);     {remove data initialization code before                           any allocations}
  653.         InitGraf(@thePort);
  654.         InitFonts;
  655.         FlushEvents(everyEvent,0);
  656.         InitWindows;
  657.         InitMenus;
  658.         TEInit;
  659.         InitDialogs(NIL);
  660.         InitCursor;
  661.         { call the routine that does printing }
  662.         FirstBoxValue := 0;         { value of our first additional box }
  663.         SecondBoxValue := 0;      { value of our second addtl. box }
  664.         PrOpen;    { Open the Print Manager }
  665.         IF PrError = noErr THEN
  666.             err := Print     { This actually brings up the modified Job                          dialog }
  667.         ELSE BEGIN
  668.             {tell the user that PrOpen failed}
  669.         END;
  670.         PrClose;    { Close the Print Manager and leave }
  671.     END.
  672. The Lightspeed C Example Program
  673. /* NOTE: Apple reserves the top half of the screen (where the current DITL
  674. items are located). Applications may use the bottom half of the screen to add items, but should not change any items in the top half     of the screen. An application should expand the print dialogs only as much as is absolutely necessary.
  675. */
  676. /* Note: A global search and replace of 'Job' with 'Stl' will produce 
  677.     code that modifies the style dialogs */
  678. #include <DialogMgr.h>
  679. #include <MacTypes.h>
  680. #include <Quickdraw.h>
  681. #include <ResourceMgr.h>
  682. #include <WindowMgr.h>
  683. #include <pascal.h>
  684. #include <printmgr.h>
  685. #define nil 0L
  686. static TPPrDlg PrtJobDialog;        /* pointer to job dialog */
  687. /*    This points to the following structure:
  688.     
  689.       struct { 
  690.           DialogRecord    Dlg;          (The Dialog window)
  691.           ProcPtr        pFltrProc;    (The Filter Proc.)
  692.           ProcPtr        pItemProc;    (The Item evaluating proc. --                             we'll change this)
  693.           THPrint        hPrintUsr;    (The user's print record.)
  694.           Boolean        fDoIt;    
  695.           Boolean        fDone;    
  696.               (Four longs -- reserved by Apple Computer)
  697.           long            lUser1;         
  698.           long            lUser2;        
  699.           long            lUser3;    
  700.           long            lUser4;        
  701.    } TPrDlg; *TPPrDlg;          
  702. */
  703. /*    Declare ‘pascal’ functions and procedures */
  704. pascal Boolean PrDlgMain();        /* Print manager’s dialog handler */
  705. pascal TPPrDlg PrJobInit();        /* Gets standard print job dialog. */
  706. pascal TPPrDlg MyJobDlgInit();    /* Our extention to PrJobInit */
  707. pascal void MyJobItems();        /* Our modal item handler */
  708. #define MyDITL 256            /* resource ID of my DITL to be spliced
  709.                             on to job dialog */
  710. THPrint hPrintRec;            /* handle to print record */
  711. short FirstBoxValue = 0;        /* value of our first additional box */
  712. short SecondBoxValue = 0;        /* value of our second addtl. box */
  713. long prFirstItem;                /* save our first item here */
  714. long prPItemProc;            /* we need to store the old itemProc here */
  715. /*-----------------------------------------------------------------------*/
  716.     WindowPtr     MyWindow;
  717.     OSErr     err;
  718.     Str255     myStr;
  719. main()
  720. {    
  721.     Rect         myWRect;
  722.     
  723.     InitGraf(&thePort);
  724.     InitFonts();
  725.     InitWindows();
  726.     InitMenus();
  727.     InitDialogs(nil);
  728.     InitCursor();
  729.        SetRect(&myWRect,50,260,350,340);
  730.     
  731.     /* call the routine that does printing */
  732.     PrOpen();
  733.     err = Print();
  734.     
  735.     PrClose();
  736. } /* main */
  737. /*------------------------------------------------------------------------*/
  738. OSErr Print()
  739. {
  740.     /* call PrJobInit to get pointer to the invisible job dialog */
  741.     hPrintRec = (THPrint)(NewHandle(sizeof(TPrint)));
  742.     PrintDefault(hPrintRec);
  743.     PrValidate(hPrintRec);
  744.     if (PrError() != noErr)
  745.         return PrError();        
  746.     PrtJobDialog = PrJobInit(hPrintRec);
  747.     if (PrError() != noErr)
  748.         return PrError();        
  749.     
  750.     if (!PrDlgMain(hPrintRec, &MyJobDlgInit))    /* this line does all the stuff */
  751.         return Cancel;
  752.     if (PrError() != noErr)
  753.         return PrError();        
  754.     
  755. /* that's all for now */
  756.         
  757. } /* Print */
  758. /*------------------------------------------------------------------------*/
  759. pascal TPPrDlg MyJobDlgInit (hPrint)
  760. THPrint hPrint;
  761. /* this routine appends items to the standard job dialog and sets up the
  762.     user fields of the printing dialog record TPRDlg 
  763.     This routine will be called by PrDlgMain */
  764. {
  765.     short        firstItem;        /* first new item number */
  766.     
  767.     short        itemType;        /* needed for GetDItem/SetDItem call */
  768.     Handle    itemH;
  769.     Rect        itemBox;
  770.     
  771.     firstItem = AppendDITL (PrtJobDialog, MyDITL); /*call routine to do                                     this */
  772.     
  773.     prFirstItem = firstItem; /* save this so MyJobItems can find it */
  774.     
  775. /* now we'll set up our DITL items -- The "First Box" */
  776.     GetDItem(PrtJobDialog,firstItem,&itemType,&itemH,&itemBox);
  777.     SetCtlValue(itemH,FirstBoxValue);
  778.     
  779. /* now we'll set up the second of our DITL items  -- The "Second Box" */
  780.     GetDItem(PrtJobDialog,firstItem+1,&itemType,&itemH,&itemBox);
  781.     SetCtlValue(itemH,SecondBoxValue);
  782.     
  783. /* Now comes the part where we patch in our item handler.  We have to save
  784.     the old item handler address, so we can call it if one of the standard items is     hit, and put our item handler's address in pItemProc field of the TPrDlg struct
  785. */
  786.     prPItemProc = (long)PrtJobDialog->pItemProc;
  787.     
  788. /* Now we'll tell the modal item handler where our routine is */
  789.     PrtJobDialog->pItemProc = (ProcPtr)&MyJobItems;
  790.     
  791. /* PrDlgMain expects a pointer to the modified dialog to be returned.... */
  792.     return PrtJobDialog;
  793.     
  794. } /*myJobDlgInit*/
  795. /*-----------------------------------------------------------------------*/
  796. /* here's the analogue to the SF dialog hook */
  797. pascal void MyJobItems(theDialog,itemNo)
  798. TPPrDlg    theDialog;
  799. short     itemNo;
  800. { /* MyJobItems */
  801.     short     myItem;
  802.     short     firstItem;
  803.     
  804.     short        itemType;        /* needed for GetDItem/SetDItem call */
  805.     Handle    itemH;
  806.     Rect        itemBox;
  807.     
  808.     firstItem = prFirstItem; /* remember, we saved this in myJobDlgInit */
  809.     myItem = itemNo-firstItem+1;    /* "localize" current item No */
  810.     if (myItem > 0)     /* if localized item > 0, it's one of ours */
  811.     {
  812.         /* find out which of our items was hit */
  813.         GetDItem(theDialog,itemNo,&itemType,&itemH,&itemBox);
  814.         switch (myItem)
  815.         {
  816.             case 1:
  817.                 /* invert value of FirstBoxValue and redraw it */
  818.                 FirstBoxValue ^= 1;
  819.                 SetCtlValue(itemH,FirstBoxValue);
  820.                 break;
  821.             case 2:
  822.                 /* invert value of SecondBoxValue and redraw it */
  823.                 SecondBoxValue ^= 1;
  824.                 SetCtlValue(itemH,SecondBoxValue);
  825.                 break;
  826.             default: Debugger(); /* OH OH */    
  827.         } /* switch */
  828.     } /* if (myItem > 0) */
  829.     else /* chain to standard item handler, whose address is saved in
  830.             prPItemProc */
  831.     {
  832.         CallPascal(theDialog,itemNo,prPItemProc);
  833.     }
  834. } /* MyJobItems */
  835. The Rez Source
  836. #include "types.r"
  837. resource 'DITL' (256) {
  838.     {    /* array DITLarray: 2 elements */
  839.         /* [1] */
  840.         {8, 0, 24, 112},
  841.         CheckBox {
  842.             enabled,
  843.             "First Box"
  844.         };
  845.         /* [2] */
  846.         {8, 175, 24, 287},
  847.         CheckBox {
  848.             enabled,
  849.             "Second Box"
  850.         }
  851.     }
  852. };
  853. Further Reference:
  854. •    The Printing Manager
  855. •    The Dialog Manager
  856. PR 10 - A Printing Loop That Cares…
  857. Printing    
  858. Revised by:    Pete “Luke” Alexander    October 1990
  859. Written by:    Ginger Jernigan    September 1987
  860. This Technical Note discusses opening and closing the Printing Manager with calls to _PrOpen and _PrClose as well as how to handle errors at print time.
  861. Changes since October 1989:  Added the section on error checking, incorporating the error code descriptions formerly found in Technical Note #72, Optimizing For The LaserWriter—Techniques and an updated version of the information formerly found in Technical Note #118, How To Check and Handle Printing Errors.
  862. Introduction
  863. At one time, Apple recommended that developers call _PrOpen at the beginning of their application and _PrClose at the end, before returning to the Finder.  This recommendation was in the ancient past when an application only had to deal with a single printer driver.
  864. As more printer drivers became available, it became important for an application to consider the presence of other applications and how opening and closing the printer driver affected them.  The user could open the Chooser at any time and change the current printer driver without the current application’s knowledge.  If an application followed the old philosophy and a user changed the current printer driver while running the application, the next time the user attempted to print, the wrong driver would be open, the Printing Manager would not be able to find the necessary resources, and the user would get an error.
  865. The Current Recommendation
  866. DTS currently recommends that applications open and close the printer driver each time the application uses the Printing Manager.
  867. MPW Pascal
  868. *------ PrintStuff ----------------------------------------------------------------*}
  869. {**
  870.  **    PrintStuff will call all of the necessary Print Manager calls to print
  871.  **    a document.  It checks PrError() after each Print Manager call.  If an
  872.  **    error is found, all of the Print Manager open calls (i.e., PrOpen,
  873.  **    PrOpenDoc...) will have a corresponding close call before the error
  874.  **    is posted to the user.  You want to use this approach to make sure the
  875.  **    Print Manager closes properly and all temporary memory is released.
  876.  **}
  877. PROCEDURE PrintStuff;
  878. VAR
  879.   copies,
  880.   firstPage,
  881.   lastPage,
  882.   loop,
  883.   numberOfCopies,
  884.   pageNumber,
  885.   printmgrsResFile,
  886.   realNumberOfPagesInDoc  : Integer;
  887.   PrintError              : LongInt;
  888.   oldPort                 : GrafPtr;
  889.   thePrRecHdl             : THPrint;
  890.   thePrPort               : TPPrPort;
  891.   theStatus               : TPrStatus;
  892. BEGIN
  893.   GetPort(oldPort);
  894.   {**
  895.       UnLoadTheWorld will swap out ALL unneeded code segments and data that are NOT
  896.       required
  897.       during print time. Your print code must be a separate code segment.
  898.   **}
  899.   UnLoadTheWorld;
  900.   thePrRecHdl := THPrint(NewHandle(SIZEOF(TPrint)));
  901.   IF (MemError = noErr) AND (thePrRecHdl <> NIL) THEN
  902.     BEGIN
  903.       PrOpen;
  904.         IF (PrError = noErr) THEN
  905.           BEGIN
  906.             {**
  907.                 Save the current resource file (i.e. the printer driver's)
  908.                 so the driver will not lose its resources upon return from
  909.                 the pIdleProc.
  910.              **}
  911.             printmgrsResFile := CurResFile;
  912.             PrintDefault(thePrRecHdl);
  913.             IF (PrError = noErr) THEN
  914.               BEGIN
  915.                 IF (PrStlDialog(thePrRecHdl)) THEN
  916.                   BEGIN
  917.                     {**
  918.                         DetermineNumberOfPagesinDoc determines the number of
  919.                         pages contained in the document by comparing the size of
  920.                         the document with rPage from the TPrInfo record (IM II-150).
  921.                         It returns the number of pages required to print the
  922.                         document for the currently selected printer.
  923.                      **}
  924.                     realNumberOfPagesinDoc := DetermineNumberOfPagesinDoc
  925.                                                   (thePrRecHdl^^.prInfo.rPage);
  926.                     IF (PrJobDialog(thePrRecHdl)) THEN 
  927.                       BEGIN
  928.                         {**
  929.                             Get the number of copies of the document that the
  930.                             user wants printed from iCopies of the TPrJob record
  931.                             (IM II-151).
  932.                          **}
  933.                         numberOfCopies := thePrRecHdl^^.prJob.iCopies;
  934.                         {**
  935.                             Get the first and last pages of the document that
  936.                             were requested to be printed by the user from iFstPage
  937.                             and iLastPage from the TPrJob record (IM II-151).
  938.                          **}
  939.                         firstPage := thePrRecHdl^^.prJob.iFstPage;
  940.                         lastPage := thePrRecHdl^^.prJob.iLstPage;
  941.                         {**
  942.                             Print "all" pages in the print loop
  943.                          **}
  944.                         thePrRecHdl^^.prJob.iFstPage := 1;
  945.                         thePrRecHdl^^.prJob.iLstPage := 9999;
  946.                         {**
  947.                             Determine the "real" number of pages contained in
  948.                             the document.  Without this test, you would print
  949.                             9999 pages.
  950.                          **}
  951.                         IF (realNumberOfPagesinDoc < lastPage) THEN
  952.                           lastPage := realNumberOfPagesinDoc;
  953.                         PrintingStatusDialog := GetNewDialog(257, NIL, POINTER(-1));
  954.                         
  955.                         {**
  956.                             Print the number of copies of document requested by the
  957.                   user
  958.                             from the Print Job Dialog.
  959.                          **}
  960.                         For copies := 1 To numberOfCopies Do
  961.                           BEGIN
  962.                             {**
  963.                                 Install a pointer to your pIdle proc in my print                     record.
  964.                              **}
  965.                              thePrRecHdl^^.prJob.pIdleProc :=                             @checkMyPrintDialogButton;
  966.                             {**
  967.                                 Restore the resource file to the printer driver's.
  968.                              **}
  969.                             UseResFile(printmgrsResFile);
  970.                             thePrPort := PrOpenDoc(thePrRecHdl, NIL, NIL);
  971.                             IF (PrError = noErr) THEN
  972.                               BEGIN
  973.                                 {**
  974.                                     Print the range of pages of the document                         requested
  975.                                     by the user from the Print Job Dialog.
  976.                                  **}
  977.                                 pageNumber := firstPage;
  978.                                 WHILE ((pageNumber <= lastPage) AND (PrError =                    noErr)) DO
  979.                                   BEGIN
  980.                                     PrOpenPage(thePrPort, NIL);
  981.                                       IF (PrError = noErr) THEN
  982.                                         BEGIN
  983.                                           {**
  984.                                               rPage (IM II-150) is the printable
  985.                                               area for the currently selected                                printer.
  986.                                               By passing the current enables your                            app to use the same routine to draw to                               the screen and the printer's GrafPort.
  987.                                            **}
  988.                                           DrawStuff (thePrRecHdl^^.prInfo.rPage, 
  989.                                                      GrafPtr (thePrPort), 
  990.                                                      pageNumber);
  991.                                         END;
  992.                                       PrClosePage(thePrPort);
  993.                                       pageNumber := pageNumber + 1;
  994.                                   END;  {**  End pagenumber loop  **}
  995.                               END;
  996.                             PrCloseDoc(thePrPort);
  997.                           END;  {**  End copies loop  **}
  998.                           {**
  999.                               The printing job is being canceled by the request of
  1000.                               the user from the Print Style Dialog or the Print Job
  1001.                               Dialog.  PrError will be set to iPrAbort to tell the
  1002.                               Print Manager to abort the current printing job.
  1003.                            **}
  1004.                       END
  1005.                         ELSE
  1006.                       PrSetError(iPrAbort);   {**  Cancel from the job dialog  **}
  1007.                   END
  1008.                     ELSE
  1009.                   PrSetError(iPrAbort);   {**  Cancel from the style dialog  **}
  1010.               END;
  1011.           END;
  1012.     IF (thePrRecHdl^^.prJob.bJDocLoop = bSpoolLoop) and (PrError = noErr) THEN
  1013.       PrPicFile(thePrRecHdl, NIL, NIL, NIL, theStatus);
  1014.     {**
  1015.         Grab the printing error before you close the Print Manager and the error 
  1016.         disappears.
  1017.      **}
  1018.     PrintError := PrError;
  1019.     PrClose;
  1020.     {**
  1021.         You do not want to report any printing errors until you have fallen
  1022.         through the printing loop. This will make sure that ALL of the Print
  1023.         Manager's open calls have their corresponding close calls, thereby
  1024.         enabling the Print Manager to close properly and that all temporary
  1025.         memory allocations are released.
  1026.      **}
  1027.     IF (PrintError <> noErr) THEN
  1028.       PostPrintingErrors (PrintError);
  1029.     END;
  1030.   IF (thePrRecHdl <> NIL) THEN 
  1031.     DisposHandle(Handle (thePrRecHdl));
  1032.   IF (PrintingStatusDialog <> NIL) THEN 
  1033.     DisposDialog(PrintingStatusDialog);
  1034.   SetPort(oldPort);
  1035. END;  {**  PrintStuff  **}
  1036. MPW C
  1037. /*------ PrintStuff ----------------------------------------------------------------*/
  1038.  **
  1039.  **    PrintStuff will call all of the necessary Print Manager calls to print
  1040.  **    a document. It checks PrError() after each Print Manager call. If an error
  1041.  **    is found, all of the Print Manager open calls (i.e., PrOpen, PrOpenDoc...)
  1042.  **    will have a corresponding close call before the error is posted to the user.
  1043.  **    You want to use this approach to make sure the Print Manager closes properly
  1044.  **    and all temporary memory is released.
  1045.  **/
  1046. void PrintStuff ()
  1047. {
  1048.   GrafPtr      oldPort;
  1049.   short        copies,
  1050.                firstPage,
  1051.                lastPage,
  1052.                numberOfCopies,
  1053.                printmgrsResFile,
  1054.                realNumberOfPagesinDoc,
  1055.                pageNumber,
  1056.                PrintError;
  1057.   THPrint      thePrRecHdl;
  1058.   TPPrPort     thePrPort;
  1059.   TPrStatus    theStatus;
  1060.   GetPort(&oldPort);
  1061.  /**
  1062.      UnLoadTheWorld will swap out ALL unneeded code segments and data that
  1063.      are NOT required during print time. Your print code must be a separate
  1064.      code segment.
  1065.   **/
  1066.   UnLoadTheWorld ();
  1067.   thePrRecHdl = (THPrint)  NewHandle (sizeof (TPrint));
  1068.  /**
  1069.      Check to make sure that the memory manager did not produce an error
  1070.      when it allocated the print record handle and make sure it did not pass
  1071.      back a nil handle.
  1072.   **/
  1073.   if (MemError() == noErr && thePrRecHdl != nil)
  1074.     {
  1075.       PrOpen();
  1076.       if (PrError() == noErr)
  1077.         {
  1078.          /**
  1079.               Save the current resource file (i.e. the printer driver's) so
  1080.               the driver will not lose its resources upon return from the pIdleProc.
  1081.           **/
  1082.           printmgrsResFile = CurResFile();
  1083.           PrintDefault(thePrRecHdl);
  1084.           if (PrError() == noErr)
  1085.             {
  1086.               if (PrStlDialog(thePrRecHdl))
  1087.                 {
  1088.                  /**
  1089.                      DetermineNumberOfPagesinDoc determines the number of pages
  1090.                      contained in the document by comparing the size of the document
  1091.                      with rPage from the TPrInfo record (IM II-150). It returns the
  1092.                      number of pages required to print the document for the                    currently selected printer.
  1093.                   **/
  1094.                   realNumberOfPagesinDoc = DetermineNumberOfPagesinDoc  
  1095.                                                ((**thePrRecHdl).prInfo.rPage);
  1096.                   if (PrJobDialog(thePrRecHdl)) 
  1097.                     {
  1098.                      /**
  1099.                           Get the number of copies of the document that the user 
  1100.                           wants printed from iCopies of the TPrJob record (IM II-                 151).
  1101.                       **/
  1102.                       numberOfCopies = (**thePrRecHdl).prJob.iCopies;
  1103.                        /**
  1104.                            Get the first and last pages of the document that
  1105.                            were requested to be printed by the user from iFstPage
  1106.                            and iLastPage from the TPrJob record (IM II-151).
  1107.                         **/
  1108.                       firstPage = (**thePrRecHdl).prJob.iFstPage;
  1109.                       lastPage = (**thePrRecHdl).prJob.iLstPage;
  1110.                        /**
  1111.                            Print "all" pages in the print loop
  1112.                         **/
  1113.                       (**thePrRecHdl).prJob.iFstPage = 1;
  1114.                       (**thePrRecHdl).prJob.iLstPage = 9999;
  1115.                        /**
  1116.                            Determine the "real" number of pages contained in the                  document. Without this test, you would print 9999 pages.
  1117.                         **/
  1118.                       if (realNumberOfPagesinDoc < lastPage) 
  1119.                         lastPage = realNumberOfPagesinDoc;
  1120.                       PrintingStatusDialog = GetNewDialog(257, nil, (WindowPtr) -1);
  1121.                        /**
  1122.                            Print the number of copies of the document
  1123.                            requested by the user from the Print Job Dialog.
  1124.                         **/
  1125.                       for (copies = 1; copies <= numberOfCopies; copies++)
  1126.                         {
  1127.                          /**
  1128.                              Install a pointer to your pIdle proc in my print                      record.
  1129.                           **/
  1130.                           (**thePrRecHdl).prJob.pIdleProc =                               checkMyPrintDialogButton;
  1131.                          /**
  1132.                              Restore the resource file to the printer driver's.
  1133.                           **/
  1134.                           UseResFile(printmgrsResFile);
  1135.                           thePrPort = PrOpenDoc(thePrRecHdl, nil, nil);
  1136.                           if (PrError() == noErr)
  1137.                             {
  1138.                              /**
  1139.                                  Print the range of pages of the document 
  1140.                                  requested by the user from the Print Job Dialog.
  1141.                               **/
  1142.                               pageNumber = firstPage;
  1143.                               while (pageNumber <= lastPage && PrError() == noErr)
  1144.                                 {
  1145.                                   PrOpenPage(thePrPort, nil);
  1146.                                   if (PrError() == noErr) 
  1147.                                     {
  1148.                                      /**
  1149.                                          rPage (IM II-150) is the printable area
  1150.                                          for the currently selected printer. By                          passing the current port to the draw                              routine, enables your app to use the same                          routine to draw to the screen and the                          printer's GrafPort.
  1151.                                       **/
  1152.                                       DrawStuff ((**thePrRecHdl).prInfo.rPage, 
  1153.                                                  (GrafPtr) thePrPort, pageNumber);
  1154.                                     }
  1155.                                   PrClosePage(thePrPort);
  1156.                                   pageNumber++;
  1157.                                 }  /**  End pageNumber loop  **/
  1158.                             }
  1159.                           PrCloseDoc(thePrPort);
  1160.                         } /**  End copies loop  **/
  1161.                     }
  1162.                    /**
  1163.                        The printing job is being canceled by the request of the
  1164.                        user from the Print Style Dialog or the Print Job Dialog.
  1165.                        PrError will be set to PrAbort to tell the Print Manager to
  1166.                        abort the current printing job.
  1167.                     **/
  1168.                   else
  1169.                     PrSetError (iPrAbort);   /**  cancel from the job dialog  **/
  1170.                 }
  1171.               else
  1172.                 PrSetError (iPrAbort);   /**  cancel from the style dialog  **/ 
  1173.             }
  1174.         }
  1175.       if (((**thePrRecHdl).prJob.bJDocLoop == bSpoolLoop) && (PrError() == noErr))
  1176.         PrPicFile(thePrRecHdl, nil, nil, nil, &theStatus);
  1177.        /**
  1178.            Grab the printing error before you close the Print Manager
  1179.            and the error disappears.
  1180.         **/
  1181.       PrintError = PrError();
  1182.       PrClose();
  1183.        /**
  1184.            You do not want to report any printing errors until you have fallen
  1185.            through the printing loop. This will make sure that ALL of the Print
  1186.            Manager's open calls have their corresponding close calls, thereby
  1187.            enabling the Print Manager to close properly and that all temporary
  1188.            memory allocations are released.
  1189.         **/
  1190.       if (PrintError != noErr) 
  1191.         PostPrintingErrors (PrintError);
  1192.     }
  1193.   if (thePrRecHdl != nil)
  1194.     DisposHandle((Handle) thePrRecHdl);
  1195.   if (PrintingStatusDialog != nil)
  1196.     DisposDialog(PrintingStatusDialog);
  1197.   SetPort(oldPort);
  1198. }  /** PrintStuff **/
  1199. Checking And Handling Printing Errors
  1200. An application should always check for error conditions while printing by calling PrError.  PrError returns errors from the Printing Manager (and some AppleTalk and OS errors) that occur during printing.
  1201. As the example code demonstrates, an application should call PrError after each call to a Printing Manager function or procedure.  By consistently checking PrError after each call, the application is able to catch any errors created at print time and report them to a user via a dialog box in a clean and graceful manner.
  1202. The following section outlines some general error-handling guidelines.
  1203. •    You should avoid calling PrError within your pIdle procedure; errors that occur while it is executing are usually temporary and serve only as internal flags for communication within the printer driver—they are not intended for the application.  If you absolutely must call PrError within your idle procedure, and an error occurs, never abort printing within the idle procedure itself.  Wait until the last called printing procedure returns, then check to see if the error still remains.  Attempting to abort printing within an idle procedure is a guarantee of certain death.
  1204. •    Upon detecting an error after the completion of a printing routine, stop drawing at that point, and proceed to the next procedure to close any previously made open calls.  For example, if you detect an error after calling PrOpenDoc, skip to the next PrCloseDoc.  Or, if you get an error after calling PrOpenPage, skip to the next PrClosePage and PrCloseDoc.  Remember that if you have called PrOpen, then you must call the corresponding PrClose to ensure that printing closes properly and all temporary memory allocations are released and returned to the heap.
  1205. •    Do not display any alert or dialog boxes to report an error until the end of the printing loop.  Once at the end, check for the error again; if there is no error assume that printing completed normally.  If the error is still present, then you can alert the user.
  1206.     This technique is important for two reasons.  First, if you display a dialog box in the middle of the printing loop, it could cause errors that can terminate an otherwise normal job.  For example, if the printer is an AppleTalk printer, the connection can be terminated abnormally since the driver would be unable to respond to AppleTalk requests received from the printer while the dialog box was waiting for input from the user.  If the printer does not hear from the Macintosh with a short period of time (e.g., 30 seconds), it times out, assuming that the Macintosh is no longer there, which results in a prematurely broken connection causing another error to which the application must respond.
  1207.     In addition, the driver may have already displayed its own dialog box in response to an error.  In this instance, the driver posts an error to let the application know that something went wrong and it should abort printing.  For example, when the LaserWriter driver detects that the Laser Prep version which has been downloaded to the LaserWriter is different than that with which the user is trying to print, it displays the appropriate dialog box informing the user of the situation and giving him the option of reinitializing the printer.  If the user chooses to cancel printing, the driver posts an error to let the application know that it needs to abort, but since the driver has already taken care of the error by displaying a dialog box, the error is reset to zero before the printing loop is complete.  The application should check for the error again at the end of the printing loop, and if it still indicates an error, the application can then display the appropriate dialog box.
  1208. •    If using PrGeneral, be prepared to receive the following errors:  NoSuchRsl, OpNotImpl, and resNotFound.  In all three cases, the application should be prepared to continue to print without using the features of that particular opcode.
  1209.     However, in the case of the resNotFound error, it means the current printer driver does not support PrGeneral.  This lack of support should not be a problem for an application, but it needs to be prepared to deal with this error.  If you receive a resNotFound error from PrError, clear the error with a call to PrSetError(0); otherwise, PrError might still contain this error the next time you check it, which would prevent your application from printing.
  1210. Canceling or Pausing the Printing Process
  1211. If you install a procedure for handling requests to cancel printing, with an option to pause the printing process, beware of timeout problems when printing to the LaserWriter.  Communication between the Macintosh and the LaserWriter must be maintained to prevent a job or a wait timeout.  If there is no communication for a period of time (over two minutes), the printer times out and the print job terminates due to a wait  timeout.  Or, if the print job requires more than three minutes to print, the print job terminates due to a job timeout.  Since, there is no good method to determine to what type of printer an application is printing, it is probably a good idea to document the possibility of a LaserWriter timing out for a user who chooses to select “pause” for over two minutes.
  1212. Error Messages Created In Print Land…
  1213. The Printing Manager reports the error messages covered in this section.  If an error that does not belong to the Printing Manager occurs, the Printing Manager puts it into low memory, where it can be retrieved with a call to PrError, and terminates the printing loop, if necessary.  As already documented, if you encounter an error in the middle of a printing loop, do not jump out; fall through the loop and let the Printing Manager terminate properly.
  1214. Error Code    Constant    Description
  1215.     0    noErr    No error
  1216.     128    iPrAbort    Abort the printing process 
  1217.             (Command-period)
  1218.     -1    iPrSavePFil    Problem saving print file
  1219.     -17    controlErr    Unimplemented Control call
  1220.     -27    iIOAbort    I/O problems
  1221.     -108    iMemFullErr    Not enough heap space
  1222. The following errors are specific to the LaserWriter family:
  1223.     -4101        Printer not found or closed
  1224.     -4100        Connection just closed
  1225.     -4099        Write request too big
  1226.     -4098        Request already active
  1227.     -4097        Bad connection refnum
  1228.     -4096        No free Connect Control Blocks (CCBs) available
  1229.     -8133        PostScript error occurred during transmission of data to printer.  Most often caused by a bug in the PostScript code being downloaded.
  1230.     -8132        Timeout occurred.  This error is returned when no data has been sent to the printer for two minutes.  Usually caused by extremely long imaging time.
  1231.     -8131        Printer not responding:  it may have been turned “off.”  This error occurs if a user turns off the LaserWriter in the middle of a print job.
  1232. The following errors are specific to PrGeneral:
  1233.     1    NoSuchRsl    Requested resolution is not supported
  1234.     2    OpNotImpl    Requested PrGeneral opcode not implemented in the current printer driver.
  1235.     -192    resNotfound    The current printer driver does not support PrGeneral.
  1236. The most common error encountered is -4101, which is generated if no LaserWriter is selected.  Since this error is so common, it is a good idea to display a dialog box requesting the user to select a printer from the Chooser when this error is encountered.
  1237. Further Reference:
  1238. •    Inside Macintosh, Volume II-145 & V-410, The Printing Manager
  1239. •    Technical Note M.IM.DevIndPrinting —
  1240.          Device-Independent Printing
  1241. •    d e v e l o p, July 1990, Issue 3, “Meet PrGeneral”
  1242. PR 11 - Programmatic PostScript Files
  1243. Printing    
  1244. Written by:    Matt Deatherage & Hugo Ayala    September 1992
  1245. This Technical Note discusses how to make the LaserWriter driver, versions 7.0 and later, create PostScript files from your printing loop, and when this is and is not appropriate.
  1246. Topics
  1247. • Creating PostScript files
  1248. • The LaserWriter driver is not a PostScript conversion utility
  1249. • Sample functions for creating an appropriate print record
  1250. I get to make PostScript files?
  1251. Yes, but don’t get too excited yet.  The feature we’re about to describe is not applicable in every case where you might want to generate PostScript code, so it’s not a generic solution.  Like those standardized tests used to say, “Please read all the directions before marking the page.”
  1252. There are definitely situations where forcing the LaserWriter driver to create a PostScript file has advantages.  It’s extremely handy for many large, multi-network Macintosh installations that have unique printing needs.  It can be handy for people using non-AppleTalk PostScript printers.  It’s a very useful capability in this and dozens of other situations.
  1253. What it’s not useful for is generic PostScript conversion.
  1254. The LaserWriter driver was designed expressly for the purpose of converting QuickDraw calls to PostScript for high-resolution imaging on Apple’s PostScript printers.  As the years have gone by, it’s been adapted to things that weren’t part of the original design model (like driving non-Apple PostScript printers).  One of the features added in recent years was the capability to dump a PostScript file when printing.  This was originally only a debugging feature for the convenience of the engineers working on the driver, but when it was made accessible to users through a hidden dialog item and a not-so-secret key combination, the response was overwhelming.  In response, the printing engineers included the capability to pick a PostScript file for output was built into versions 7.0 and later of the driver.
  1255. That didn’t change the fact that it was still, at heart, a glorified debugging feature.  The PostScript the driver creates is designed expressly for printing.  It does not create Encapsulated PostScript files (EPSF format).  It doesn’t easily incorporate any PostScript document conventions other than the one it uses for its own benefit.  It doesn’t generate PostScript Level 2.  It includes large amounts of custom encrypted code to provide TrueType™ font rendering technology on PostScript printers where possible.
  1256. It’s important to understand that you can’t change any of this.  If you have a strong need to programmatically create files just like the LaserWriter driver would create if you chose the “PostScript file” radio button in the job dialog, this technique is for you.  If you need anything more customizable, or more specialized, or in a different format, this Note is not for you.  The LaserWriter driver is not and never has been a generic PostScript conversion utility; if you want such capabilities, you must still build them into your application.
  1257. How to Do the Deed
  1258. The LaserWriter driver stores the PostScript file information in the print record—but not in a format designed for your easy access.  To make it print to a PostScript file, you have to set a bit, fill in a vRefNum , a dirID and a pointer to the file name—all inside a private LaserWriter driver structure.
  1259. The flag is a bit in the word starting at offset $52 (or 82 decimal) of the print record.  This is documented as boolean value f2 of the printer flags record prFlag1.  Figure 1 shows a redeclaration of this record with the newly-documented fPSFile bit included.
  1260.    lwTPrFlag1 = PACKED RECORD
  1261.                    f15: BOOLEAN;
  1262.                    f14: BOOLEAN;
  1263.                    f13: BOOLEAN;
  1264.                    f12: BOOLEAN;
  1265.                    f11: BOOLEAN;
  1266.                    f10: BOOLEAN;
  1267.                    f9: BOOLEAN;
  1268.                    f8: BOOLEAN;
  1269.                    f7: BOOLEAN;
  1270.                    f6: BOOLEAN;
  1271.                    f5: BOOLEAN;
  1272.                    f4: BOOLEAN;
  1273.                    f3: BOOLEAN;
  1274.                    fPSFile: BOOLEAN;
  1275.                    fLstPgFst: BOOLEAN;
  1276.                    fUserScale: BOOLEAN;
  1277.                 END;
  1278. Figure 1—Redefined PrFlag1 Record
  1279. Note that the record is renamed beginning with lw to emphasize that this technique only works with the LaserWriter driver.    This means you have to check that you’re printing to the LaserWriter driver by making sure the high byte of TPRStl.wDev is 3, for the LaserWriter driver.  If other drivers impersonate the LaserWriter driver (which they may do, for example, so that your application sends them PostScript in picture comments), this may crash.  Unfortunately, Apple can’t conclusively tell you that a third-party printer driver will or will not support this feature.  Apple’s driver does.
  1280. Where does the LaserWriter driver put the new PostScript file?  The word starting at offset $68 (104 decimal) is the vRefNum for the file to save, and the long at offset $70 is the directory ID for where to store the file.    The long starting at $6A (or 106 decimal in the print record) is a pointer to the PostScript file name as a Pascal string—just the file name; the other fields indicate the other portions of the file’s specification (in fact, they’re all three portions of an FSSpec record).
  1281. However, the name pointer isn’t just any old pointer.  There’s some baggage with it.
  1282. First, the LaserWriter driver always assumes that it allocated the pointer, and somewhere in the printing loop, when it’s done with the PostScript file name, it calls DisposPtr on that pointer.  That means you must allocate it with NewPtr and it must be valid during the print loop, or your heap becomes toast.  It should be a 64-byte pointer, because the driver assumes that’s what it is.
  1283. Second, the LaserWriter driver assumes that it’s the only one who would be messing with this private field in the print record, so it only clears it during PrJobInit.  That means when you're done printing, your print record will still contain a pointer to the memory that used to point to the file name string.  If you save this print record and try to print again without going through the job dialog, the LaserWriter driver will use it as a pointer on your behalf, even though it probably doesn’t point to anything useful anymore.  Also, if the pointer is non-NIL entering the job dialog (if somehow someone bypasses PrJobInit), it also assumes it’s a pointer and uses it.  So, before you save or use this print record for anything, always zero the file name pointer.  It will save many hassles down the road.
  1284. Third, if you encounter a print record that has the fPSFile bit (bit 3 of offset $52) already set, the LaserWriter driver has already validated the information in the print record.  The pointer has been allocated and the directory information stored.  Do not override these values or you may cause a memory leak.
  1285. The driver also saves in the print record, in the next two bytes starting at $6E, the vRefNum of the last volume used to store a PostScript file.  It also uses the directory ID field at offset $70 to indicate the last directory used for storing a PostScript file.  This is only so the Standard File dialog put up by PrJobDialog can start with the most appropriate directory; it’s not important to programmatic control of this mechanism.
  1286. Figure 2 shows the LaserWriter driver’s version of the print record, redeclared with the newly-documented information as lwTHPrint:
  1287. TYPE
  1288.    { Print Job: Print "form" for a single print request. }
  1289.    lwTPPrint = ^lwTPrint;
  1290.    lwTHPrint = ^lwTPPrint;
  1291.    lwTPrint = RECORD
  1292.                  iPrVersion: INTEGER; {(2) Printing software version}
  1293.                  prInfo: TPrInfo; {(14) the PrInfo data associated with the
  1294.                                    current style.}
  1295.                  rPaper: Rect; {(8) The paper rectangle [offset from rPage]}
  1296.                  prStl: TPrStl; {(8) This print request's style.}
  1297.                  prInfoPT: TPrInfo; {(14) Print Time Imaging metrics}
  1298.                  prXInfo: TPrXInfo; {(16) Print-time (expanded) Print info
  1299.                                      record.}
  1300.                  prJob: TPrJob; {(20) The Print Job request (82) Total of the
  1301.                                  above; 120-82 = 38 bytes needed to fill 120}
  1302.                  CASE INTEGER OF
  1303.                     0:
  1304.                        (printX: ARRAY [1..19] OF INTEGER);
  1305.                     1:
  1306.                        (prFlag1: TPrFlag1; {a word of flags}
  1307.                         iZoomMin: INTEGER;
  1308.                         iZoomMax: INTEGER;
  1309.                         hDocName: StringHandle; {current doc's name, nil =
  1310.                                                  front window}
  1311.                         reservedAndWeMeanIt: ARRAY [1..6] OF INTEGER;
  1312.                         psFileVRefNum: INTEGER;
  1313.                         pPSFileName: Ptr;
  1314.                         lastVRefNum: INTEGER;
  1315.                         lastDirID: Longint; );
  1316.               END;
  1317. Figure 2—Redefined Print Record
  1318. When you print in the foreground, the LaserWriter driver uses the information in the print record to create the PostScript file.  When you print in the background, the LaserWriter driver adds a resource with the information to the spool file so PrintMonitor can do the same thing.  This lets this method work in both the foreground and background cases.
  1319. Be careful about picking file names to use—whatever method you use, if the file name is not unique, the LaserWriter driver will attempt to delete the existing file and cause you, as Hugo puts it, “endless grief.”  Simply examining the directory at spooling time isn’t enough if there’s any chance the file name might not be unique when PrintMonitor gets around to despooling the file.  Furthermore, if you try to write over an existing file, the LaserWriter driver will not change the end-of-file position, so the result file will have the larger EOF of the new file and the old contents.  This is also Bad.
  1320. Here’s a summary of what we’ve discussed:
  1321. 1.    Get a print record ready to start your printing loop.
  1322. 2.    Change the fPSFile bit to tell the LaserWriter driver to create a PostScript file instead.
  1323. 3.    Set the vRefNum and directory ID for where you want to store the file.
  1324. 4.     Allocate a 64-byte pointer to store the file name; put the filename in the new memory block and put the pointer in the print record.
  1325. 5.    Complete your print loop as normal.
  1326. 6.    Zero the file name pointer in the print record as a precaution.
  1327. 7.    Save or otherwise manipulate the print record for future use.
  1328. Samples?  Sure.
  1329. The following System 7-only sample routine PrPSFileDialog can be used in place of PrJobDialog when using this technique.  Note that the routine requires a handle of type lwTHPrint.
  1330. Note:    Be careful about bypassing the job dialog.  The LaserWriter driver resets some other job-specific parameters (besides the file to save PostScript in) in PrJobMain.  If you save a print record immediately after calling PrJobDialog and use that print record without going through the job dialog again, all of the job-specific parameters will be preserved (number of copies, page range, feeder choice, etc.).  This may not be what you intended.
  1331. FUNCTION PrPSFileDialog(thePrRecHdl: lwTHPrint): BOOLEAN;
  1332.    VAR
  1333.       ourReply: StandardFileReply;
  1334.       tempFlags: INTEGER;
  1335.       tempResult: BOOLEAN;
  1336.       ourOSError: OSErr;
  1337.       tempPtr: Ptr;
  1338.    BEGIN
  1339.       PrPSFileDialog := FALSE; { being conservative }
  1340.       tempResult := PrValidate(THPrint(thePrRecHdl));
  1341.       IF NOT thePrRecHdl^^.prFlag1.fPSFile THEN
  1342.       { don't do this if there's already a file to be saved! }
  1343.          BEGIN
  1344.          StandardPutFile('Save PostScript file as','PostScript',ourReply);
  1345.          IF ourReply.sfGood THEN {Did the user accept a file to save as?}
  1346.             BEGIN
  1347.             IF ourReply.sfReplacing THEN BEGIN
  1348.                ourOSError := FSpDelete(ourReply.sfFile); { make sure this is
  1349.                                                           gone before we
  1350.                                                           start! }
  1351.                IF ourOSError <> noErr THEN AlertUser;
  1352.             END;
  1353. {OK, we're finally ready to pound the print record.  Put on your division by zero suit...}
  1354.             thePrRecHdl^^.prFlag1.fPSFile := TRUE;
  1355.             thePrRecHdl^^.psFileVRefNum := ourReply.sfFile.vRefNum;
  1356.             tempPtr := NewPtr(64); {Size of reply.fName. }
  1357.             IF tempPtr = NIL THEN AlertUser; {SERIOUSLY low on memory }
  1358. {The LaserWriter driver will Dispos of this pointer before the end of the print loop.}
  1359.             thePrRecHdl^^.pPSFileName := tempPtr;
  1360.             BlockMove(@ourReply.sfFile.name,thePrRecHdl^^.pPSFileName,
  1361.                       (LENGTH(ourReply.sfFile.name) + 1));
  1362.             thePrRecHdl^^.lastDirID := ourReply.sfFile.parID; {ID of
  1363.                user-chosen directory}
  1364.             PrPSFileDialog := TRUE;
  1365.          END {IF good THEN…}
  1366.       END {if flag was clear}
  1367.    END;
  1368. PR 12 - SetLineWidth Revealed
  1369. Printing    
  1370. Revised by:        March 1988
  1371. Written by:    Scott "ZZ" Zimmerman    November 1987
  1372. This technical note describes the internal implementation, and correct method of using, the SetLineWidth Picture Comment.
  1373. The SetLineWidth picture comment provides a way of accessing PostScript’s 'setlinewidth' operator. Since the LaserWriter resolution is roughly four times that of the Macintosh screen, fractional line widths can be printed. The SetLineWidth PicComment provides a way for applications to access these fractional line widths through PostScript, without having to use floating point numbers.
  1374. First of all, the LaserWriter has an internal state that is stored in a number of PostScript variables. For more information on PostScript variables, see the PostScript Language Reference Manual. Some operations performed on the LaserWriter cause the values of these variables to change. One of these variables contains the width of the printer’s pen. The SetLineWidth picture comment works by changing the value of this variable.
  1375. Before we look at what the SetLineWidth comment does, let’s look at the argument passed to the comment. The argument is represented as a QuickDraw Point, however it is interpreted by the LaserWriter as a fraction. The LaserWriter interprets a point(h,v) to be a real number whose value is (v / h). This means that a point whose value is h=2, v=1, will be converted to 0.5 before being used by the LaserWriter. If you wanted to pass a value of 0.25, you would pass a point whose value is h=4, v=1. For 1.25, pass a point, h=4, v= 5.
  1376. In addition to the pen width variable, there is a variable that is used for scaling the pen’s width. This variable, named pnm for PeN Multiplier, contains a real number which is applied to the pen width. The default value of pnm is 1.0, which causes no scaling of the line width.
  1377. Whenever the SetLineWidth PicComment is sent to the LaserWriter, the current value of pnm is replaced by the value passed to the PicComment. The current pen size is then scaled by the new value of pnm. The following example will display four lines of different sizes. It is meant to illustrate the interaction between the QuickDraw PenSize procedure and the SetLineWidth PicComment.
  1378. TYPE
  1379.     widthHdl    = ^widthPtr;
  1380.     widthPtr    = ^widthPt;
  1381.     widthPt     = Point;
  1382. VAR
  1383.     theWidth:   widthHdl;
  1384. BEGIN
  1385.     (* Initialize the print manager as per Inside Macintosh II-155. *)
  1386. At this point, it is assumed that PrPageOpen has been called, and the print manager is ready to accept data.
  1387. The first thing we do is set the scaling factor to 1.0. This way, no scaling will be performed when we call PenSize.
  1388.     theWidth := widthHdl(NewHandle(SizeOf(widthPt)));
  1389.     (*Real programs do error checking here... *)
  1390.     SetPt(theWidth^^, 1, 1);
  1391.     PicComment(SetLineWidth, SIZEOF(widthPt), Handle(theWidth));
  1392. Here we call PenSize. Because the pnm has been set to 1.0, the pen size(1,1) times the multiplier (1.0) yields 1,1.
  1393.     PenSize(1, 1);
  1394.     MoveTo(50, 100);
  1395.     LineTo(500, 100);
  1396.     MoveTo(50, 125);
  1397.     DrawString('1 point thickness.');
  1398. Now we will use the SetLineWidth PicComment to change the pen size. Note that when we change the scaling factor, the pen size changes as well.
  1399.     SetPt(theWidth^^, 1, 5);
  1400.     PicComment(SetLineWidth, SIZEOF(widthPt), Handle(theWidth));
  1401.     MoveTo(50, 200);
  1402.     LineTo(500, 200);
  1403.     MoveTo(50, 225);
  1404.     DrawString('5.0 times 1 point pen size = 5 point thickness.');
  1405. If any calls to PenSize are made at this point, the new pen size will be scaled by 5.0. This is because the SetLineWidth PicComment is still in effect. We will now send a SetLineWidth PicComment to revert the scaling factor back to 1.0.
  1406.     SetPt(theWidth^^, 5, 1);
  1407.     PicComment(SetLineWidth, SIZEOF(widthPt), Handle(theWidth));
  1408.     MoveTo(50, 300);
  1409.     LineTo(500,300); 
  1410.     MoveTo(50, 325);
  1411.     DrawString('0.2 times 5 point pen size = 1 point thickness.');
  1412. Since the scaling is once again 1.0, PenSize calls at this point will not be scaled. Here we explicitly set the scaling factor to 1.0 before changing the pen size. This makes it easier to see what scaling will be applied to the next call to PenSize.
  1413.     SetPt(theWidth^^, 1, 1);
  1414.     PicComment(SetLineWidth, SIZEOF(widthPt), Handle(theWidth));
  1415.     PenSize(1, 1);
  1416.     MoveTo(50, 400);
  1417.     LineTo(500,400); 
  1418.     MoveTo(50, 425);
  1419.     DrawString('1.0 times 1 point pen size = 1 point thickness');
  1420.     (* Dispose of the handle when you are through with it! *)
  1421.     DisposHandle(Handle(theWidth));
  1422. When printed, the above example will produce the following:
  1423. To summarize, there are four things to remember when using the SetLineWidth PicComment:
  1424. 1.    The argument to the SetLineWidth PicComment is specified as a point, though it is actually interpreted by the LaserWriter as a real number. The point value is specified as h,v, and the LaserWriter interprets the value as v / h.
  1425. 2.    The SetLineWidth PicComment affects both the height and width of the pen, even though the name suggests otherwise.
  1426. 3.    When you send the SetLineWidth PicComment, the current pen size will be scaled. Any drawing that is done after the PicComment is set, will be done with the scaled pen size.
  1427. 4.    When you call the QuickDraw PenSize procedure, the pen size will be scaled after it has been set. For example, if your scaling factor is 0.5, and you set the pen size to 2,2, the  actual pen size will be 1,1. If you don’t want the scaling to occur, make sure to send a  SetLineWidth PicComment, with the point argument set to 1,1.  The next call to PenSize will then be scaled by 1.0, which will have no effect.
  1428. Further Reference:
  1429. •    LaserWriter Reference Manual
  1430. •    PostScript Language Reference Manual
  1431. •    PostScript Language Tutorial and Cookbook
  1432. PR 13 - Spooler Queries?
  1433. Printing    
  1434. Revised by:        March 1988
  1435. Written by:    Ginger Jernigan    July 1987
  1436. When the LaserShare spooler is on an AppleTalk network, it acts like a LaserWriter-type device, which can be chosen and communicated with much like a real LaserWriter. Some applications, however, must communicate with a LaserWriter directly, not a spooler. If this is true for your application, you can check whether you are actually talking to a real LaserWriter by sending to the LaserWriter the following query:
  1437.     %!PS-Adobe-1.2 Query
  1438.     %%Title: Query to Spooler/Non-Spooler status
  1439.     %%?BeginSpoolerQuery
  1440.     (0) = flush
  1441.     %%?EndSpoolerQuery 1
  1442.     %%EOF
  1443. (The query has to be sent using the Printer Access Protocol (PAP). The object code for PAP is available from Licensing.) If the string returned begins with a ‘%%’ then it is a status string and you can ignore it and wait for another string. If the LaserWriter is actually a LaserShare spooler, then the string that is returned will be ‘1’. If the LaserWriter is a real LaserWriter then the string returned will be ‘0’.
  1444. Further Reference:
  1445. •    PostScript Language Reference Manual
  1446. •    Adobe Systems Document Structuring Conventions
  1447. PR 14 - Dictionary Downloading
  1448. Printing    
  1449. Written by:    Zz Zimmerman    April 1991
  1450. This technical note discusses a method for downloading PostScript dictionaries automatically using the LaserWriter driver.  It will also provide the format and use of the PREC(103) resource.  It will also describe some problems with the now obsolete PREC(201) resource.  If you are using PostScript dictionaries, or either of these resources, you should definitely read this note.
  1451. Introduction
  1452. Although many picture comments have been added to support the features of PostScript that are missing from Quickdraw, many developers have still taken to sending PostScript directly from their applications.  As the use and complexity of this PostScript code increases, more and more developers are finding it necessary to define and use their own PostScript dictionaries.  PostScript dictionaries are basically collections of variables and procedures that can be predefined, and accessed later.  They are used to prevent conflicts between the symbols used by applications and those used by system software (such as the LaserWriter driver's LaserPrep dictionary).  Unfortunately, because of the LaserWriter drivers habit of using the PostScript 'save' and 'restore' operators, there are problems with keeping a PostScript dictionary defined.  PostScript definitions made by code sent with the print job (ie. sent between the calls to PrOpenPage/PrClosePage) will be lost the first time the LaserWriter driver calls 'restore'.  There are a couple of solutions to this problem, but one that hasn't been documented before involves the use of the PREC(103) resource.  If the LaserWriter driver finds a resource of type PREC with an ID of 103, it will download the PostScript code to the LaserWriter before performing the initial 'save' operation.  This means that any definitions made by the PostScript code stored in the PREC(103) resource will remain defined for the duration of the print job, independent of the LaserWriter driver's calls to save and restore.
  1453. Caveats
  1454. The PREC(103) method is a great way to get a dictionary downloaded at print time.  Unfortunately, this does not solve the problem for using dictionaries in export files like PICT.  If you insert PostScript code into Quickdraw pictures, the system is not smart enough to record the PREC(103) code into the picture.  Instead, you must record the dictionary using the standard PostScript picture comments (defined in Technical Note #91, Optimizing for the LaserWriter–PicComments).  You should also use the appropriate PostScript structuring comments as defined by the Adobe Document Structuring Conventions.  If you use the Adobe comments correctly, an application that is importing your picture will have the option of parsing for the procedure set comments, and extracting the dictionary definition to be placed in a PREC(103) resource at print time.
  1455. The next caveat concerns the use of multiple PREC(103) resources.  At PrOpenDoc time, the LaserWriter driver makes one GetResource call to load the resource of type PREC with an ID of 103.  Because the call is a GetResource call (instead of Get1Resource), the PREC can be stored in any open resource file.  To avoid any conflicts, the resource should be stored in the resource fork of your application, or in the document file that is referencing the PostScript dictionary.  Because the GetResource call is only made once, only the first PREC resource found by GetResource will be used.  Any other PREC(103) resources will be ignored.  As long is this resource is only used by applications, there is no problem since there can only be one application active at any particular time.  If the resource is used by other elements of the system (ie. desk accessories, drivers, INITs), you can easily run into the problem of your PREC resource being ignored.  The best solution to this problem is to only use the resource from within an application.
  1456. Since the PREC(103) resource is considered part of the print job, the definitions it makes are lost when the job ends (ie. when the LaserWriter receives EndOfFile from the Macintosh).  Because of this, the code you place in the PREC(103) resource should not attempt changing any persistent parameters in the printer.  The means avoiding the PostScript 'exitserver' operator.  You should also avoid calling other routines that reset the current state of the printer (ie. initclip, initgraphics, etc.).  Use of these operators will have a serious effect on Quickdraw operations that may be present in the print job.
  1457. When the PREC(103) resource was originally introduced, it had a cousin called PREC(201).  PREC(201) was similar to the PREC(103) resource in that it allowed PostScript to be downloaded to the printer before the actual print job.  The difference between the two resources was that the PREC(201) resource downloaded the PostScript code at the same time that it downloaded the LaserPrep dictionary, outside of the PostScript 'server loop'.  Because of this, any definitions made by the code in the PREC(201) resource would remain after the current job.  Like the LaserPrep dictionary, the dictionary downloaded in PREC(201) would remain until the LaserWriter was rebooted (ie. powered off then on again).  Although this feature was useful in some situations, it did have its problems.  Not the least of which was the valuable printer memory consumed by the dictionary that was downloaded.  Since the dictionary remained after the job that required it, subsequent jobs had less memory available to them.  The only way to reclaim the memory was to reboot the printer, and this was not obvious to naive users.  The other problem was introduced when background printing became available.  With background printing enabled, the LaserWriter driver could no longer count on the PREC(201) resource always being available.  Since you could no longer store the resource in the LaserWriter driver (because of the LaserWriter driver being MultiFinder compatible - see Learning To Drive for more information), it has to be stored in a separate resource file.  This made it virtually impossible for the LaserWriter driver to find the resource when it was required.  For this reason, the PREC(201) resource is only downloaded when background printing is turned off.
  1458. Needless to say, we don't recommend the use of features that only work in certain situations, so the PREC(201) resource is now considered unsupported and obsolete.  If you are using the PREC(201) resource, you should be able to revise your application to use the PREC(103) resource instead, with only a small performance penalty.  On the bright side, the PREC(201) resource will continue to be supported in the foreground through the 7.0 version of the LaserWriter driver, and most likely, until the new printing architecture becomes available, giving you plenty of time to revise...
  1459. Implementation
  1460. The PREC(103) resource can be implemented by simply creating the resource with ResEdit or Rez, and then storing it in an open resource file at print time.  In the case of ResEdit, you should create a new resource of type PREC with an ID of 103.  You should then open the new resource using the resource template for string ('STR ') resources.  You can then type your PostScript code directly into the resource.
  1461. If you would rather keep your PREC definition as a Rez source file with the rest of your project, you can do this by simply defining the PREC resource type at the top of the file, followed by an instance of the PREC resource.  Consider the following Rez source code:
  1462.     /* First the resource type definition: */
  1463.     type 'PREC' {
  1464.         string;
  1465.     };
  1466.     /* Now the real resource definition: */
  1467.     resource 'PREC' (103) {
  1468.         "userdict /mydict 50 dict def";
  1469.     };
  1470. We begin by defining the resource type as being a string.  We then define an instance of the resource with an ID of 103.  Finally, we define the contents of the resource.  The PostScript code above basically defines a dictionary named mydict within the userdict dictionary.  The mydict dictionary is defined as having a maximum of 50 elements.  Consult the PostScript Language Reference Manual for more information concerning legal operations on dictionaries.
  1471. Conclusion
  1472. The PREC(103) is a simple, efficient way to download a PostScript dictionary at print time.  It does not solve the problem of exporting PostScript that references a dictionary into file formats such as PICT, but it can help.  Applications can be revised to extract PostScript dictionary definitions from files such as PICT and download them at print time using the PREC(103).  It should be noted however that this is not automatic, the application must parse the picture to get this functionality.  Finally, the PREC(201) resource can only be supported when background printing is disabled, so it is now considered obsolete, and use of it is unsupported.
  1473. Further Reference:
  1474. •    PostScript Language Reference Manual, Adobe Systems Inc.
  1475. •    Adobe Document Structuring Conventions, Adobe Systems Inc.
  1476. •    LaserWriter Reference Manual, Addison-Wesley
  1477. PostScript is a registered trademark of Adobe Systems Incorporated.
  1478. PR 15 - Feeder Fodder
  1479. Printing    
  1480. Written by:    Zz Zimmerman    April 1991
  1481. This Technical Note discusses the new Feeder button available in the 6.1, and 7.0 versions of the LaserWriter driver.  This Feeder button mechanism allows developers to insert code into the LaserWriter driver to support a sheet feeder connected to a LaserWriter.  This Note provides a description of the button, as well as information required to implement one.
  1482. Introduction
  1483. The LaserWriter driver now implements a standard method for handling sheet feeders.  Most LaserWriter sheet feeders need a way to present a user with a dialog as well as a way to download the PostScript® code necessary to control the feeder.  In the past, most manufacturers resorted to modifying the LaserWriter driver’s code resources; however, this functionality is now possible without the need to patch existing resources in the driver—by adding three new resources.
  1484. When the LaserWriter driver notices these three special resources in its resource fork, it displays a Feeder button in the lower right corner of the Print dialog box.  It is important to note that this feature is not provided for general application use, but rather only for developers of sheet feeders and other LaserWriter add-on devices.  The button is always labeled Feeder, and there can be only one set of Feeder resources in the LaserWriter driver.  Because of this restriction, you should not attempt to use this feature to implement anything other than a sheet feeder.
  1485. The first special resource contains code to implement the user interface of the feeder, and the other two contain the PostScript code required to drive the feeder.  When an application calls the LaserWriter driver to display the Print dialog box, the driver looks for three resources of type 'feed' and displays the Feeder button in the lower right corner of the dialog box if they are found.  If no 'feed' resources are available, it does not display the Feeder button.
  1486. When a user selects Print, the driver displays the standard Print dialog box with the Feeder button.  If a user clicks on the Feeder button, the driver displays a dialog box in front of the Print dialog box, which allows the user to configure the feeder, then returns to the Print dialog box once the user confirms or cancels the feeder configuration.  This feeder dialog box should not contain an option to print, as this could override choices made in the standard Print dialog box.
  1487. Implementation
  1488. To handle interaction with the user, you must install a resource of type 'feed' (ID = -8192) into the LaserWriter driver with the code required to manage the dialog box.  Like all Printing Manager code resources, this resource begins with a jump table, followed by the actual code.  The code is implemented as a procedure that is passed a single parameter.  This parameter is a rectangle defining the page size selected by the user.  This page size is equivalent to the rPaper rectangle in the print record, meaning it defines the actual page size, not just the printable area.  The rectangle is expressed in 72 dpi coordinates and has a negative origin.
  1489. Go Ahead and Jump
  1490. The jump table consists of a 68000 JMP instruction that jumps to the proper offset in the resource.  In this case, there is only one routine, so the code starts immediately following the jump table.  To make this step automatic, the jump table is created using a small assembly language header:
  1491.         IMPORT    Feeder        ; Feeder is NOT defined here...
  1492.     Start    MAIN    EXPORT        ; This is the main entry point for the linker.
  1493.         JMP    Feeder        ; The one jump table entry in this table.
  1494.         END
  1495. This example first imports the Feeder procedure, which can be defined externally in the language of your choice.  Next is Start, the main entry point to the jump table.  By passing this label to the link command, the jump table is located at the beginning of the resource.  The next line is the actual jump table entry, and the END is required to end the assembly-language header.  That’s all there is to it.  The only thing one should have to change in this code fragment would be the name of the routine to import.
  1496. The Real MacCode
  1497. Now that the jump table is complete, it needs some place to jump.  Although MPW C and Pascal examples are provided in this Note, the code can be written in any language.  As mentioned before, the code is implemented as a procedure that takes one parameter.
  1498. C Definition
  1499. In C, this looks like:
  1500.     #include <Types.h>
  1501.     #include <Quickdraw.h>
  1502.     void FEEDER(Rect *r)
  1503.     {
  1504.         <Code to present and handle dialog...>
  1505.     }
  1506. Since the assembler converts all labels to uppercase, the name of the procedure FEEDER must be capitalized to match the case of the label in the jump table.  If you are using MPW, you can use the assembler's CASE directive to prevent the assembler from capitalizing the labels.  Since the rectangle is passed using the C calling convention (i.e., the caller strips the parameter), there is no need to declare the procedure as type Pascal.  However, this convention does make things a little more interesting for the Pascal version:
  1507. Pascal Definition
  1508. If you are using MPW, you can use the Pascal compiler's C directive to define the Feeder procedure as using the C calling convention.  This makes the definition look like this:
  1509.     UNIT FeederSample;
  1510.         INTERFACE 
  1511.             USES Types, Quickdraw;
  1512.         PROCEDURE Feeder(r: Rect); C;
  1513.         IMPLEMENTATION
  1514.         PROCEDURE Feeder(r: Rect);
  1515.         BEGIN        
  1516.             <Code to present and handle dialog...>
  1517.         END;
  1518.     END.
  1519. So this is straight forward.  The procedure Feeder is defined as having one parameter (r), and the C directive is used so that the stack is handled correctly. 
  1520. If you are using some other development environment that doesn't support the C directive, you have to do a little more work, making the definition look like this:
  1521.     UNIT FeederSample;
  1522.         INTERFACE 
  1523.             USES Types, Quickdraw;
  1524.         PROCEDURE Feeder;
  1525.         IMPLEMENTATION
  1526.         FUNCTION StealRectalParam: Rect;
  1527.             INLINE    $2EAE, 0008;        { MOVE.L        8(A6),(A7) }
  1528.         PROCEDURE Feeder;
  1529.         VAR
  1530.             r:    Rect;
  1531.         BEGIN
  1532.             r := StealRectalParam;
  1533.         
  1534.             <Code to present and handle dialog...>
  1535.         END;
  1536.     END.
  1537. First of all, a unit is defined, and the proper interfaces are included.  The definition of the Feeder procedure in the INTERFACE section is required to make the label available to external modules.  In the IMPLEMENTATION section, one starts with the StealRectalParam function, which is used to get the rectangle passed by the Printing Manager without actually removing it from the stack.  If you declared the rectangle as a parameter to the Feeder procedure, Feeder would remove the parameter before returning, then when the caller tried to remove the parameter again, the stack would be invalid and would cause a crash.
  1538. To solve this problem, define the Feeder procedure with no parameters.  This way, the Feeder procedure leaves the parameter right where the caller left it.  To get the parameter without removing it from the stack, use the StealRectalParam function, which moves the parameter from its normal location (off of A6) into the location pointed to by the stack pointer.  Since StealRectalParam is a function, the stack pointer is already pointing to the return value.  When StealRectalParam returns, the Feeder routine gets the rectangle parameter, without having removed it from the stack.
  1539. Tickled Link
  1540. Now you have the jump table and the code, but you still need to link them together.  This step is pretty simple, but remember to specify the starting location of the jump table.  It looks like the following:
  1541.     Link -w -t feed -c ZzZz -rt feed=-8192 -m START -sg Feeder ∂
  1542.         Feeder.a.o ∂              # This file MUST be first.
  1543.         Feeder.p.o ∂
  1544.         "{Libraries}"Runtime.o ∂
  1545.         "{Libraries}"Interface.o ∂
  1546.         "{PLibraries}"SANELib.o ∂
  1547.         "{PLibraries}"PasLib.o ∂
  1548.         -o Feeder
  1549. First tell the linker to link the code into a 'feed' resource with an ID of -8192.  Next, specify that the resource begins with the code at label START.  This label was defined by the assembly-language used to generate the jump table.  Finally, tell the linker to link all of the code into a single segment named Feeder.  Obviously, the list of libraries and object files changes depending upon the language used, but the directives to the Link command should remain the same.
  1550. Well Fed
  1551. So that should be enough to get some code into the 'feed' resource.  Now you need to actually control the feeder during the print job.  To do this, you must use PostScript.  Your driver should also provide a 'feed' resource of -8191 containing PostScript code.  This code is downloaded by the LaserWriter driver prior to downloading the rest of the job.  For those familiar with the 'PREC' 103 resource, the PostScript in the 'feed' resource is downloaded before the 'PREC' 103 code.  Additional PostScript to be downloaded can be stored in 'feed' -8190.  The PostScript code in the 'feed' resource should redefine (i.e., patch) the PostScript operators required to handle switching feeders.  A likely candidate is the showpage operator called at the end of each page.  As always, calling or redefining operators defined by the LaserPrep (md) dictionary is not supported.  If your device is connected via the LaserWriter’s serial port, you can license code from Adobe Systems, Inc. that makes it possible to access the serial port while the LaserWriter is connected over AppleTalk.  For more information, contact Adobe at:
  1552.             Adobe Systems, Inc.
  1553.             1585 Charleston Road
  1554.             Mountain View, CA  94043
  1555.             (415) 961-4400
  1556. Once a user has confirmed the configuration from the dialog box, you can edit the PostScript code in the -8191 resource to reflect the choices made.  However, when MultiFinder is active, you cannot add or change the size of resources in the LaserWriter driver.  For this reason, you should pad the 'feed' -8191 resource to the maximum size.  This padding can be done by adding spaces at the end.  If you later need to resize the resource, you can simply overwrite some of the spaces.  For more information on printer drivers under MultiFinder, see the Learning to Drive document, which is part of “Developer Essentials,” and is available on AppleLink, the Apple FTP site, and the Developer CD Series.
  1557. You probably need to provide other resources along with the 'feed' resources; for example, you need 'DITL' and 'DLOG' resources for the dialog box.  This is okay, but you should be sure to pick unique resource types to avoid confusing the LaserWriter driver.  In the case of a Feeder button, you are a guest in someone else’s house.  It would be wise to avoid rearranging the furniture.
  1558. When the LaserWriter driver actually opens the connection to the printer, it looks for 'feed' resources -8191 and -8190.  If they exist, they are downloaded.  For those familiar with the 'PREC' 103 method of downloading PostScript code (refer to Technical Note #192, Surprised in LaserWriter 5.2 and Newer), the 'feed' resources are downloaded before the 'PREC' 103 resource.  In the case of background printing, the resources are copied into the spool file.  Since 'feed' resources -8191 and -8190 are automatically downloaded by the LaserWriter, they must contain PostScript code.  The format of these PostScript resources is a string of ASCII characters without any length byte or terminator.  The size of the string is determined by the size of the resource; there are no special size restrictions on these resources, and their only requirement is that they contain PostScript code.  To make debugging easier, you should separate lines of PostScript using a carriage return character (13 or $0D hex).
  1559. Don't Feed The Print Monster
  1560. One last important note concerns the 6.1 version of the LaserWriter driver, shipped on the Macintosh Printing Tools disk included with the Personal LaserWriter LS and StyleWriter.  In this version of the driver, the Feeder button will only work when Background printing is disabled.  There is a problem with the driver finding the 'feed' resources when Background printing is enabled.  This problem has been solved in the 7.0 version of the driver which should be used instead of the 6.1 driver as soon as it is available.  Since there is no workaround for the problem, you don't really have to do anything except for possibly noting it in your documentation.  Any note should recommend upgrading to the 7.0 version of the driver as soon as possible.
  1561. Driving Miss Lasey
  1562. Now that you have the two or three 'feed' resources, the big question is installation.  How should you ship these things?  There are two methods.  The first method involves licensing the LaserWriter driver from Apple Software Licensing (SW.License on AppleLink).  This method is only required for “turn-key” systems, where all installation is done for the user and you must ship the LaserWriter driver as part of your product.  The second method, which is by and large preferred as it requires no licensing, is to ship your resources in an installer application.  This application simply opens the LaserWriter file and adds the necessary resources.
  1563. Conclusion
  1564. So this should be all the information you need to implement the feed resources for your device.  If you intend to drive a sheet feeder through the LaserWriter’s serial port, be sure to contact Adobe Systems, Inc. for the most current implementation and licensing information.  Although the Feeder button could theoretically be used for other purposes, it will always be labeled “Feeder” by the LaserWriter driver.  Because of this consistency, developers should not attempt to extend its functionality beyond support for sheet feeders.
  1565. Further Reference:
  1566. •    PostScript Language Reference Manual, Adobe Systems Inc.
  1567. •    Technical Note M.IM.LWDriverSuprises —
  1568.          Surprises in LaserWriter 5.2 and Newer
  1569. PostScript is a registered trademark of Adobe Systems Incorporated.
  1570. PR 16 - Fun With PrJobMerge
  1571. Printing    
  1572. Revised by:    Matt Deatherage    May 1992
  1573. Written by:    Scott “Zz” Zimmerman and Matt Deatherage    March 1992
  1574. This Technical Note discusses some interesting behavior you’ll encounter while using PrJobMerge with the 7.0 and 7.1 versions of the LaserWriter driver.
  1575. Changes since March 1992:  Corrected the Vulcan-like “THPring” typo to correctly read “THPrint,” and changed a comment in the code to mean what I originally meant.
  1576. Like many Printing Manager calls, PrJobMerge is implemented by the currently chosen printer driver. This makes sense after consideration—since the printer driver may store job-specific information anywhere in the print record, only the printer driver can correctly merge this into a destination print record.
  1577. The LaserWriter driver’s implementation of PrJobMerge has a few bugs in versions 7.0 and 7.1.
  1578. Fun Thing #1
  1579. Historically, PrJobMerge hasn’t worked correctly in the LaserWriter driver. The driver does not correctly merge all job-related data (like the number of copies requested) into the destination print record, so printing multiple copies of multiple documents from the Finder isn’t really possible with the LaserWriter driver.
  1580. The only possible workaround is to present a different job dialog for each document to be printed, but this isn’t recommended—especially since the job dialog doesn’t tell you which document you’re about to print.
  1581. Fun Thing #2
  1582. As if this wasn’t enough excitement for one driver, in versions 7.0 and 7.1 of the LaserWriter driver PrJobMerge actually manages to destroy all the job-specific information in the source print record after it doesn’t copy it into the destination print record.
  1583. There is a workaround for this problem—make a copy of the source print record and pass the copy to PrJobMerge. If you pass the copy to PrJobMerge, you can just replace PrJobMerge with your own routine that makes a copy, merges it into the destination, and disposes of the copy. This will work for all printer drivers, although it’s necessary only with version 7.0 of the LaserWriter driver.
  1584. Such a procedure might look like this in Pascal:
  1585. PROCEDURE NewPrJobMerge(hPrintSrc,hPrintDst: THPrint);
  1586.     VAR
  1587.         copyError: OSErr;
  1588.         hPrintTemp: THPrint;
  1589.     BEGIN
  1590.         hPrintTemp := hPrintSrc;  {make our own copy of the print record handle}
  1591.         copyError := HandToHand(Handle(hPrintTemp));
  1592.         PrSetError(copyError); {so we can get it later}
  1593.         IF copyError = noErr THEN BEGIN
  1594.             {hPrintTemp is now a copy of the original source record}
  1595.             PrJobMerge(hPrintTemp,hPrintDst); {This messes up hPrintTemp, but we
  1596.                                                don't care}
  1597.         END; {if copyError = noErr}
  1598.         IF hPrintTemp <> NIL THEN DisposHandle(Handle(hPrintTemp)); {only a copy,
  1599.                                                                      remember!}
  1600.     END;
  1601. Don’t Go Overboard Trying to Solve This
  1602. Although the bugs in PrJobMerge in versions 7.0 and 7.1 of the LaserWriter driver make certain kinds of printing multiple documents impossible without device-specific workarounds, we strongly encourage you not to implement such code. Any code that tries to replicate the function of PrJobMerge must by nature depend on how the LaserWriter driver stores information in the print record, and this is a Bad Thing. The road to Compatibility Hell is paved with good intentions.
  1603. If you write your code as described in this Note, it will behave properly when the bug is fixed without change on your part. If you go overboard trying to write your own PrJobMerge function, your application is a prime candidate for compatibility problems.
  1604. Further Reference:
  1605. •    Inside Macintosh, Volume II, The Printing Manager
  1606. PR 17 - ImageWriter II Paper Motion
  1607. Printing    
  1608. Revised by:        March 1988
  1609. Written by:    Ginger Jernigan    April 1986
  1610. The purpose of this technical note is to answer the many questions asked about why the paper moves the way it does on the ImageWriter II.
  1611. Many people have asked why the paper is rolled backward at the beginning of a Macintosh print job on the ImageWriter II. First, note that this only happens with pin-feed paper (i.e. not with hand-feed or the sheet-feeder) and only at the beginning of a job.
  1612. It is not a bug, and it is not malicious programming. It is simply that users are told in the manual to load pin-feed paper with the top edge at the pinch-rollers, making it easy to rip off the printed page(s) without wrecking the paper that is still in the printer or having to roll the paper up and down manually. At the end of every job, the software makes sure that the paper is left in this position, leaving the print-head roughly an inch from the edge. If something is to be printed higher than that, the paper has to be rolled backwards.
  1613. As you are probably aware, the “printable rectangle” (rPage) reported to the application by the print code begins 1/2 inch from the top edge, not one inch. The reason for that is that we want a document to print exactly the same way whether you are printing on the ImageWriter I or II. On the ImageWriter I, the paper starts with the print-head 1/2 inch from the top edge, so the top of rPage is at that position for both printers.
  1614. There is no way to eliminate the reverse-feed action, because the user would have to load the paper a different way AND the software would have to know that this was done. 
  1615. Incidentally, in addition to the paper motion described above, there is also the “burp.” This is a 1/8-inch motion back and forth to take up the slop in the printer’s gear-train. It is needed on the old-model printer, and there is debate about whether or not it’s needed on ALL ImageWriter IIs, or only some, or none. The burp has been in and out of the ImageWriter II code in various releases; right now it’s in.
  1616. PR 18 - The Effect of Spool-a-page/Print-a-page on Shared Printers
  1617. Printing    
  1618. Revised by:        March 1988
  1619. Written by:    Ginger Jenigan    May 1987
  1620. This technical note discusses drawbacks of using the spool-a-page/ print-a-page method of printing.
  1621. The “spool-a-page/print-a-page” method of printing prints each page of a document as a separate job instead of calling PrPicFile to print the entire picture file. Many applications adopted this method of printing to avoid running out of disk space while the ImageWriter driver was spooling the document to disk. As long as you are printing to a directly connected ImageWriter, you’re fine, but if you are printing to remote or shared devices (like the AppleTalk ImageWriter and the LaserWriter), this method may create significant problems for the user.
  1622. When a job is initiated by the application, the driver establishes a connection with the printer via AppleTalk. When the job is completed, the driver closes the connection, allowing another job the opportunity to print. If each page is a job in itself, then the connection is closed and reopened between each page, allowing another application to print between the pages of the document, which, as you might imagine, could present a significant problem. If two people are printing to the same AppleTalk ImageWriter at the same time and their applications use the “spool-a-page/print-a-page” method of printing, the pages of each document will be interleaved at the printer.
  1623. Although there are good reasons for using this method of printing, it is only useful for a directly connected printer. From a compatibility point of view, this method of printing is built-in device dependence. Also, this method could create serious problems for other types of remote devices. Therefore, we are recommending that applications avoid using this method indiscriminately. You should check available disk space to see how much room you have before you print. If there isn’t enough space for your entire document, then print as much as you can (to minimize the interleaving) before starting another job. Whenever possible, applications should use the print loop described on page II-155 in The Printing Manager chapter of Inside Macintosh.
  1624. Further Reference:
  1625. •    Printing Manager
  1626. •    Technical Note M.IM.LaserWriterOpt — 
  1627.         Optimizing for the LaserWriter—Techniques
  1628. PR 19 - Using Laser Prep Routines
  1629. Printing    
  1630. Revised by:        March 1988
  1631. Written by:    Ginger Jernigan    July 1987    
  1632. This technical note addresses the issues involved in depending on the procedures and constants defined in the Laser Prep dictionary.
  1633. When you are writing an application that uses PostScript heavily, it is very tempting to call the procedures already defined in the Laser Prep dictionary, rather than taking up the space in the printer’s memory with PostScript procedures of your own. Or, if a procedure in the dictionary doesn’t do what you need it to do, it is tempting to go in and change it to do what you really want.
  1634. Unfortunately, we cannot guarantee that either the name or the function of a particular procedure in the dictionary will stay the same when the LaserWriter driver changes. In addition, some procedures may become obsolete and go away when the driver changes. Since the Laser Prep dictionary is considered part of the source for the LaserWriter driver, Apple reserves the right to make any changes to it that are deemed necessary.
  1635. Because we cannot guarantee the permanence of the contents of the Laser Prep dictionary, relying on its contents can pose a significant compatibility problem. If you rely on the procedures defined in the Laser Prep dictionary, your application will have to be revised every time Apple releases a new LaserWriter driver.
  1636. If you feel that you absolutely must use or modify procedures in the Laser Prep dictionary, you must always check the version that is loaded into the printer before you print. This allows your application to take appropriate action if the version of the dictionary that has been downloaded to the printer isn’t one that you know about.
  1637. How To Check The Laser Prep Dictionary Version
  1638. To determine the version of Laser Prep that the printer may contain, you have to communicate with the printer using the Printer Access Protocol (PAP); you can’t just send your query through the LaserWriter driver because there is no way to get an answer back. The object code and documentation for PAP are available from Apple’s Licensing department.
  1639. To determine whether the dictionary has been downloaded and whether it is the right one, send the following PostScript code to the printer:
  1640.     %!PS-Adobe-1.2 Query
  1641.     %%Title: Query to establish Laser Prep ProcSet version propriety
  1642.     %%?BeginProcSetQuery: AppleDict md xx
  1643.     /md where{
  1644.     /md get /av get cvi xx eq
  1645.     {(1)}{(2)}ifelse}
  1646.     {(0)}ifelse = flush
  1647.     %%?EndProcSetQuery: unknown
  1648.     %%EOF
  1649. md is the name of the Apple dictionary and xx is the version number you want.
  1650. Note: /av is a constant in the md dictionary which contains the dictionary’s version number. This is the only object in the dictionary whose name and function are guaranteed not to change.
  1651. From the printer you will receive a string. If the string returned begins with ‘%%’, it is a Status response. You can ignore it and wait for another string.
  1652. If the response is ‘0’, the dictionary hasn’t been downloaded yet; you will need to determine how to best handle this situation for your application.
  1653. If the response is ‘1’, the printer is loaded with the correct version of the dictionary.
  1654. If the response is ‘2’, then the dictionary exists but it isn’t the version you need. In this case you need to either let the user know, or proceed in as standard a fashion as possible, without calling or modifying routines contained in the Laser Prep dictionary.
  1655. Translating PostScript Files
  1656. Some applications interpret the PostScript files that are generated by the LaserWriter driver when the user presses command-F (generates document only) or command-K (generates dictionary and document) after clicking on the OK button in the Job dialog. A typical application might translate these PostScript files into another page description language.
  1657. This kind of application requires intimate knowledge of the contents of the dictionary in order to be able to do the translation, because it may have to expand the procedures used to their actual values before it can then translate the PostScript to another language. This poses a significant compatibility problem. Since we cannot guarantee that the contents of the dictionary will not change, these types of applications will have to be revised every time we release a new version of the LaserWriter driver. Also, there is no way to know which version of the LaserWriter driver generated the PostScript file the application is interpreting. You will have to require that a particular version of the LaserWriter driver be used to generate the PostScript files that your application will interpret.
  1658. Printer Independence
  1659. Applications that are written to take advantage of the routines in the Laser Prep dictionary are, of course, highly device dependent. Being device dependent can drastically reduce your chances of being compatible with future printer-type devices. For a more detailed discussion of this issue, please refer to Technical Note #122.
  1660. Further Reference:
  1661. •    The Printing Manager
  1662. •    PostScript Language Reference Manual
  1663. •    Technical Note M.IM.DevIndPrinting —
  1664.         Device-Independent Printing
  1665. PR 20 - LaserWriter Driver Surprises in 5.0 and Newer
  1666. Printing    
  1667. Revised by:    Mary Burke & Scott “Zz” Zimmerman    February 1990
  1668. Written by:    Scott “Zz” Zimmerman    April 1988
  1669. This Technical Note describes some changes in version 5.0 and later LaserWriter drivers.
  1670. Changes since April 1988:  Described a bug in 5.x which is fixed in 6.0 and later, and reiterated a warning about storing fonts in an application.
  1671. With the release of LaserWriter 5.0 and background printing, a few changes had to be made to the LaserWriter driver.  Although these changes were transparent to most applications, some have had problems.  Most of these problems are related to use of unsupported features.  This Note details a partial list of the changes.
  1672. No Mo’ Low
  1673. Because of the problems supporting both the high-level and low-level interfaces in the background, the low-level interface is all but removed.  Instead of the low-level calls being executed by the device driver, the _PrCtlCall procedure converts the call into its high-level equivalent before execution.  This way, the LaserWriter driver has a common entry point for both the low-level and high-level interfaces.  Because of this conversion, the low-level calls may not be faster than using the high-level equivalents.  In some cases, they may even be slower.
  1674. Version 5.x of the LaserWriter driver also contains a bug with the low-level interface.  If an application which uses the low-level Printing Manager interface encounters an error during the course of the print job, the LaserWriter driver crashes before the application has a chance to see the error.  Because the error occurs inside the driver, there is no way for an application to predict or work around this problem.  The only solution to this problem is to use the high-level Printing Manager interface or to upgrade to version 6.0 or later of the LaserWriter driver which fixes this bug.
  1675. Are You Convertible?
  1676. Whereas the conversion of the low-level calls should be transparent, the conversion routines make some assumptions.  The conversion routines require a context in which to operate; the Printing Manager maintains a certain state while executing commands, and the conversion routines need access to this state to perform the conversion.  To provide this context, an application must have opened a document and a page.  This requirement means that the original method of using the low-level interface, which is documented in Inside Macintosh, Volume II-164, no longer works, as in the following example:
  1677.     PrDrvrOpen;
  1678.     PrCtlCall(iPrDevCtl, lPrReset, 0, 0);
  1679.     { Send data to be printed. }
  1680.     PrCtlCall(iPrDevCtl, lPrPageEnd, 0, 0);
  1681.     PrDrvrClose;
  1682. Instead, an application should use the following:
  1683.     PrDrvrOpen;
  1684.     PrCtlCall(iPrDevCtl, lPrDocOpen, 0, 0);
  1685.     PrCtlCall(iPrDevCtl, lPrPageOpen, 0, 0);
  1686.     { Send data to be printed. }
  1687.     PrCtlCall(iPrDevCtl, lPrPageClose, 0, 0);
  1688.     PrCtlCall(iPrDevCtl, lPrDocClose, 0, 0);
  1689.     PrDrvrClose;
  1690. This method provides the Printing Manager with the context it needs to convert the calls.
  1691. Really Unsupported Features
  1692. Sending data to the printer between the _PrOpenDoc or lPrDocOpen and the _PrOpenPage or lPrPageOpen calls is not currently, and has never been supported.  LaserWriter drivers prior to 5.0 interpreted this data, but 5.0 and later drivers ignore it.  To download an application-specific PostScript® dictionary as a header with each document, Apple recommends that the application provide a 'PREC' resource of ID = 103, as is described in the LaserWriter Reference.
  1693. A Little Less Control
  1694. Four of the six printer control calls originally supported by the LaserWriter driver have been discontinued due to lack of use and difficulty supporting with background printing.  The four calls which follow were only supported by the LaserWriter driver and only documented in the LaserWriter Reference Manual:
  1695.         °•° fill    °•° hexBuf    °•° printR    °•° printF
  1696. In addition to these calls, the stdBuf call is also affected.  There are two versions of the stdBuf call depending upon the sign of the bytes parameter.  If bytes is negative, the text passed to the stdBuf call is converted to PostScript text before being sent to the LaserWriter.  This conversion means that special PostScript characters in the text are preceded by a PostScript escape character.  In addition, characters with an ASCII value greater than 128 are converted to octal before being sent to the LaserWriter.  This version of the call is no longer supported.
  1697. If the bytes parameter is positive, the text passed to the call is sent directly to the LaserWriter without conversion and interpreted as PostScript instructions.  This version of the call is still supported, but there is one more problem.  When an application first opens the low-level driver (via _PrDrvrOpen) with background printing enabled, no clip region is defined.  If the application then begins sending PostScript to the driver via the stdBuf call, all of the output is clipped, and only a blank page is printed.
  1698. To prevent this problem, the application must force a clip region to be sent to the LaserWriter.  The region is sent by the driver when it receives its first drawing command.  Unfortunately, the driver does not consider the stdBuf call to be a drawing command.  To force the clip region on the printer, the application can use the iPrBitsCtl call to print a small bitmap outside the printable area of the page.  This call does not have any effect on the document, but it fires the bottleneck routine and causes a definition of the clip region.  Since the clip region is reinitialized at each call to lPrPageOpen, the application should send the bitmap once at the start of each page.  If any other printer control calls precede the stdBuf call, the application does not need to send the bitmap.
  1699. Background Preparations
  1700. The 'PREC' ID = 201 mechanism only works when background printing is disabled.  This limitation is because of difficulties finding the resource under MultiFinder.  Since the option only works in the foreground, and since there is no way for an application to know if background printing is enabled, an application should avoid using this feature.
  1701. Fonts In An Application?
  1702. There are two problems when printing application fonts with the LaserWriter driver.  Application fonts are fonts that are stored in the resource fork of the application’s resource file rather than being stored in the System file.  The first problem occurs when the application font has the same name as the application’s resource file.  If this is the true, the LaserWriter driver incorrectly assumes that the application’s resource file is a font file, and closes it after using the font.  To solve this problem, developers should make sure the name of the application font (i.e., the 'FOND' resource) is different from the name of the application’s resource file.  Since the application can still be renamed by the user, developers should try to select a unique font name.  If the font name does not appear in a font menu, developers can simply append the application’s creator string onto the desired font name (i.e., 'MyApplicationFont ZZAP').
  1703. The second problem with application fonts only occurs when background printing is enabled.  When a print job is performed in the background, the LaserWriter driver writes all of the data to be printed into a file (called a spool file) for printing at a later time by Print Monitor.  Since the LaserWriter driver has no way of knowing when the file will actually be printed, it cannot assume that the application will still be open when the job is printed.  This is a problem if the application contains application fonts that Print Monitor needs at print time.  To solve this problem, the LaserWriter driver must determine whether the fonts needed by the application are resident in the System file or in the application file.  If they are in the application file, the driver must copy them into the spool file so they are available to Print Monitor.  This practice can lead to very large spool files, as well as a significant loss of performance when background printing is enabled.  To solve these and other user interface problems related to application fonts, Apple strongly recommends that developers ship custom application fonts as suitcase files for the user to install in the System file.
  1704. Headin’ For Trouble
  1705. There is a minor bug in version 5.0 of the LaserWriter driver that only affects applications that parse the PostScript header downloaded by the driver with each document.  This header contains some PostScript comments that provide information about the current job.  One of these comments is IncludeProcSet.  This comment takes three arguments:  a PostScript dictionary name, a major version number, and a minor version number.  In version 4.0 of the LaserWriter driver, the comment line looked like the following:
  1706.     %% IncludeProcSet: (Appledict md) 65 0
  1707. Unfortunately, in version 5.0 of the LaserWriter driver, the last argument was removed.  This caused the comment line to look like the following:
  1708.     %% IncludeProcSet (Appledict md) 66
  1709. Since Adobe defined the comment to take three arguments, it is reasonable for applications that parse the comments to expect three arguments; therefore, version 5.1 and later of the LaserWriter driver contain the correct version of the comment:
  1710.     %% IncludeProcSet (Appledict md) 67 0
  1711. No Go With Zero
  1712. Some applications want to force a font to be downloaded to the LaserWriter without actually printing characters with the font.  This can be done in three easy steps:
  1713. 1.    Save the current pen position.
  1714. 2.    Use any text drawing routine to draw a space character.
  1715. 3.    Move the pen back to the saved position.
  1716. Some applications use _DrawString with a empty string (e.g., DrawString('')) to force the font downloading. Although this worked in LaserWriter drivers up to 5.0, these calls are ignored by the 5.1 and later drivers.  The main reasons for this change were optimization of performance and a reduction in the size of spool files.
  1717. Further Reference:
  1718. •    Inside Macintosh, Volumes II & V, The Printing Manager
  1719. •    LaserWriter Reference Manual
  1720. PostScript is a registered trademark of Adobe Systems Incorporated.
  1721. PR 21 - Pictures and the Printing Manager
  1722. Printing    
  1723. Written by:    Zz Zimmerman    April 1991
  1724. This technical note described some problems and features of using Quickdraw pictures with the Printing Manager.  In general, if your application prints Quickdraw pictures, you should read this note.
  1725. Introduction
  1726. Most applications support Quickdraw pictures to some degree.  They will allow you to import or export picture files, as well as using the PICT resource format on the clipboard to support Cut & Paste with other applications.  Unfortunately, there are some problems that occur with pictures at print time, and that's what I want to cover here.
  1727. You PICT When?
  1728. One of the problems that comes up at print time is the use of picture comments.  Some applications store their data in a native format, and only create pictures at print time to enable the use of picture comments.  For each page of the document, they open a new picture, record the Quickdraw calls that described the document, along with any picture comments they want to use, and finally close the picture.  When this is done, they call DrawPicture to print the picture, and then start the whole process over again for the next page.
  1729. This method is supported and fully compatible with future system software, but is not required.  The Printing Manager spools each page of a document into a Quickdraw picture.  Since the Printing Manager already has a picture open, it is totally legal to send a picture comment (via the PicComment call) in between calls to PrOpenPage and PrClosePage without having them recorded in a picture.   The Printing Manager has already replaced the StdComment procedure with its own anyway, so the PicComment call will be intercepted and supported correctly by the Printing Manager.  If the only reason you are recording into pictures is so that you can use PicComments, you can avoid the overhead at print time by simply sending the comments directly.
  1730. Feeling PICT On?
  1731. Even if you aren't sending picture comments, you may still need to create a picture at print time.  In general, you should try to create any pictures you need prior to calling PrOpen.  This is because there is no way to predict how much memory a particular printer driver will require.  Instead, you need to make as much memory available as possible.  If you are creating pictures with the Printing Manager open, the chances are good that you are using memory you can't afford to waste.
  1732. If you need to create a picture with the Printing Manager open, and memory is not a problem, you should still be aware of some potential problems.  First of all, keep in mind the Printing Manager receives data from the application by replacing the Quickdraw GrafProcs stored in the GrafPort returned by PrOpenDoc.  One of these procedures is the StdComment procedure which is called each time the application calls the Quickdraw PicComment routine.  Since the Printing Manager has these routines patched, creating a picture in the Printing Manager's GrafPort can cause problems.  If you must create a picture between calls to PrOpenPage/PrClosePage, you should be sure to set the port to a standard Quickdraw GrafPort before calling OpenPicture.  Any GrafPort that was created by Quickdraw (as opposed to the Printing Manager) will work fine.
  1733. If you do create a picture at print time, you may experience a syndrome we call 'floating picture comments'.  That is, calls made by your application to the PicComment routine will be recorded in a different order than you made them.  This will usually cause them to effect the wrong part of the picture, and lead to endless confusion.  The best solution to this problem is to create any pictures that your application will need before opening the Printing Manager.
  1734. Scaling Pictures - Mountains from Mole Hills
  1735. Another problem is a basic problem with pictures that seems to show up more at print time.  The problem concerns the scaling of pictures using the destination rectangle passed to DrawPicture.  This method will work for most pictures, but problems arise with more complex pictures, and for pictures that contain text.  The problem is the method that Quickdraw uses to scale the text stored within pictures.  When scaling, Quickdraw tries to handle the text scaling intelligently by changing the size of the font being used, as opposed to just scaling the bits.  Unfortunately, the widths used by bitmapped fonts are not always linear (ie. the 12 point width isn't exactly 1/2 of the 24 point width).  Because of this, you can run into problems with lines of text getting slightly longer or shorter as the picture is scaled.  In many cases, the error is insignificant, but if you are trying to draw a line of text that fits exactly into a box (a spreadsheet cell for example), you might be surprised to see the line of text extending beyond the box when the picture is scaled.
  1736. There can also be problems when using certain picture comments or imbedded PostScript.  In the case of the TextCenter picture comment, you specify an offset to the center of rotation.  This offset is usually based on the metrics of the font being used.  If you scale the picture, Quickdraw decides to use a different font, and the offset you originally specified will be incorrect.
  1737. The easiest way to solve these problems is to scale the picture yourself.  Especially if you are trying to scale by a large amount.  For example, some applications create a picture at 72 dpi (ie. dots per inch), and then scale it to 288 dpi for printing by simply increasing the destination rectangle by 4x.  This is asking a lot of the system, and will result in the text problems described above.  Instead, you should either draw the picture into its original frame, and let the Printing Manager handle scaling it to the resolution of the device, or handle the scaling yourself by parsing the picture and playing it back opcode by opcode instead of calling DrawPicture.
  1738. One last thing to watch for when scaling pictures is integer overflows.  It's usually pretty rare that you will overflow a coordinate when creating a Quickdraw picture, but it is not so hard to do when scaling a picture.  For example, some applications will draw something offscreen to make sure the Printing Manager has configured the clip region and other related structures.  They usually do this by moving the cursor to (-32767,-32767), and then draw a pixel.  This works fine to initialize the Printing Manager, and the pixel isn't actually seen on the output.  The problem occurs when you try to scale this picture.  If you try to make it bigger, Quickdraw will adjust to coordinate (-32767,-32767) which will end up overflowing.  The only way to solve these problems is to look for these kinds of operations in the picture before trying to scale it with DrawPicture.
  1739. Pictures Within Pictures–Is Nesting the Best Thing?
  1740. One cool feature of Quickdraw pictures is the ability to nest them easily.  Basically, you can call OpenPicture, and then call DrawPicture with multiple pictures, and when you call ClosePicture, they will all have been recorded into one picture.  Very cool.  The problem comes when you start using the Begin/End form of picture comments.  There are some comments like PostScriptBegin/PostScriptEnd, and TextBegin/TextEnd that have a begin comment that is followed by an end comment.  When using these comments, it is very important to make sure that you have an end for each begin that you have sent.  If the nesting gets off, you will, at the least, get incorrect output, though it is more likely that the Printing Manager will actually crash.  If your application is generating picture comments, it is very simple to make sure that you have an end for each begin.  But when nesting a picture that you have imported from another application, it is important to know how its comments will interact with yours.
  1741. In most cases, you can simply call DrawPicture to render the picture to the Printing Manager and you don't have to worry.  But if you are creating a picture for export, you may have to nest multiple pictures from multiple creators into the same picture to be exported.  If this is the case, it is important to make sure that all of your begin comments have matching end comments before attempting to insert another picture.  If this is done, you can insert the imported picture without having to worry about the comments it contains.  If all of your begin/ends are matched, you can assume that the imported picture will be just as valid.
  1742. On the other hand, if you have a begin comment, and want to insert a picture before inserting the appropriate end comment, you must parse the picture to be inserted to make sure it is not using the same comment pair.  If it is, and you insert it, you will have problems.
  1743. So make sure that all your begins and ends are matched, and don't try to insert other pictures between begin/end pairs of comments.  If you find that you have to insert a picture between a pair of begin/end comments, you must parse the picture to be inserted to make sure that it does not use the same comments.
  1744. Penalty for Quickdraw - Clipping
  1745. Here's a subtle fact about Quickdraw pictures.  If you call OpenPicture, and then record some drawing operations, and you don't explicitly specify a clipping region, Quickdraw will specify one for you.  In fact, Quickdraw will use the last clip region stored in the GrafPort that you are using when you call OpenPicture.  This has been a surprise to many a developer when they record a picture, and a big piece of it ends up missing when they draw it.  This isn't specific to print time, it can happen on the screen too, but it happens enough that it's worth mentioning.
  1746. D' Resolution
  1747. If you've read Technical Note #275, Features of 32 Bit Quickdraw 1.2, you probably noticed the new font and resolution information.  Basically, fonts are now stored in pictures by name, not by ID.  This means that fonts stored in pictures will be displayed correctly on any Macintosh without fonts remapping to other faces.  The other new addition to the picture format is horizontal and vertical resolution information.  Applications that create pictures using the new OpenCPicture call will be able to tell Quickdraw the native resolution of the picture data.  So if you're a scanner that is scanning at 200 dpi, you will be able to store your data at 200 dpi (instead of scaling it to 72 dpi first).  When an application subsequently opens the picture, it can determine the picture's resolution and take the necessary steps to display it correctly (ie. scaling down for display on the 72 dpi screen, or scaling up for display on 300 dpi devices like the LaserWriter).
  1748. Conclusion
  1749. Quickdraw pictures can be used successfully at print time, if you avoid the problems described above.  Although there is a little overhead required by some of the workarounds, most are very simple to implement, and will help you avoid future compatibility problems.
  1750. Further Reference:
  1751. •    PostScript Language Reference Manual, Adobe Systems Inc.
  1752. •    LaserWriter Reference Manual, Addison-Wesley
  1753. PostScript is a registered trademark of Adobe Systems Incorporated.
  1754. PR 22 - pIdle Proc (or how to let users know what’s going on during print time…)
  1755. Printing    
  1756. Written by:    Pete “Luke” Alexander    April 1991
  1757. This Technical Note discusses how to defensively program a pIdle procedure to work with the majority of print drivers in existence today, and how to install it at print time.
  1758. Introduction
  1759. When using a pIdle procedure at print time, there are a few things that one should remember to be compatible with the printer drivers that are available today.  This Technical Note discusses installing a pIdle procedure at the right time and the things to remember when writing one.  
  1760. Installing The pIdle Proc
  1761. Let's start by installing the pIdle procedure at the right time.  You must install your pIdle procedure into the print record before calling PrOpenDoc.  If you do not install your pIdle procedure before your call to PrOpenDoc, the printer driver does not give the application's pIdle procedure any time.  The following code fragments demonstrate installing the pIdle procedure in the right place:
  1762. MPW Pascal
  1763.     << more print loop would appear above, see Tech Note #161 for details >>
  1764.     {**  Install a pointer to your pIdle proc into your print record. **}
  1765.     PrintingStatusDialog := GetNewDialog(257, NIL, POINTER(-1));
  1766.     thePrRecHdl^^.prJob.pIdleProc := @checkMyPrintDialogButton;
  1767.     thePrPort := PrOpenDoc(thePrRecHdl, NIL, NIL);
  1768.     << more print loop would follow below, see Tech Note #161 for details >>
  1769. MPW C
  1770.       << more print loop would appear above, see Tech Note #161 for details >>
  1771.     /**  Install a pointer to your pIdle proc into your print record.  **/
  1772.     PrintingStatusDialog = GetNewDialog(257, nil, (WindowPtr) -1);
  1773.     (**thePrRecHdl).prJob.pIdleProc = checkMyPrintDialogButton;
  1774.     thePrPort = PrOpenDoc(thePrRecHdl, nil, nil);
  1775.     << more print loop would follow below, see Tech Note #161 for details >>
  1776. For a complete printing loop that handles errors at print time and makes all of the right calls to the Printing Manager, refer to Technical Note #161, A Print Loop That Cares...
  1777. Things To Remember About pIdle Procedures
  1778. It is extremely important to design and code your pIdle procedure as defensively as possible,  thereby making sure that it works with as many printer drivers as possible.  This section details a few things to remember when creating pIdle procedures.
  1779. Saving And Restoring The Current Port
  1780. It is extremely important to save the printer driver’s GrafPort, upon entry to your pIdle procedure and restore it upon exit.  Why? If you do not, the printer driver  would draw into the GrafPort of your dialog box instead of it's GrafPort,which will cause some bad results.  To save the printer’s GrafPort, you should call _GetPort when entering your procedure.  Before you exit your procedure, you would call _SetPort to set the port from your dialog box back to the printer driver’s GrafPort (i.e., the one you saved with _GetPort).
  1781. Saving And Restoring The Printer Driver’s Resources
  1782. If the application changes the resource chain within it's pIdle procedure, you want to save and restore the printer driver’s resource chain.  Why?  Some printer drivers assume that their resource chain does not change, but this may not be true when the driver calls the pIdle procedure installed by the application at print time.  To accomplish this task, call _CurResFile, saving the ID of the printer driver’s resource file at the beginning of your pIdle procedure.  When you exit from your pIdle procedure, restore the resource chain back to the printer driver’s resource chain with a call to _UseResFile.  
  1783. At this point, you might be wondering what might change the resource chain. If you called _OpenResFile or _UseResFile (anything that would change the value of  the low memory global TopMapHdl) within the application's pIdle procedure, the chain would be changed.  If you are not changing the resource chain, these calls would not be needed.
  1784. Handling Errors From Within A pIdle Procedure
  1785. You should avoid calling PrError within your pIdle procedure; errors that occur while it is executing are usually temporary, and serve only as internal flags for communication within the printer driver—they are not intended for the application.  If you absolutely must call PrError within your idle procedure, and an error occurs, never abort printing within the idle procedure itself.  Wait until the last called printing procedure returns, then check to see if the error still remains.  Attempting to abort printing within an idle procedure is a guarantee of certain death.
  1786. Canceling Or Pausing The Printing Process
  1787. If you install a procedure for handling requests to cancel printing, with an option to pause the printing process, beware of timeout problems when printing to the LaserWriter.  Communication between the Macintosh and the LaserWriter must be maintained to prevent a job or a wait timeout.  If there is not any communication for a period of time (over two minutes), the printer times out and the print job terminates due to a wait  timeout.  Or, if the print job requires more than three minutes to print, the print job terminates due to a job timeout.  Since, there is not a good method to determine to what type of printer an application is printing, it is probably a good idea to document the possibility of a LaserWriter timing out for a user who chooses to select “pause” for over two minutes.
  1788. Some Printer Drivers Do Not Support pIdle Procedures
  1789. Some printer drivers do not support pIdle procedures, as they prefer to handle the pIdle procedure in their own manner without giving an application’s pIdle procedure any time.  This situation should not be a problem as long as you do not assume that your pIdle procedure is always called at print time.  Therefore, you should only create your pIdle procedure to display the dialog box and respond to a user pausing, continuing, or canceling a print job.
  1790. Conclusion
  1791. When installing your pIdle proc, it must be installed before the application calls PrOpenDoc.  You want to make sure that you save and restore the GrafPort , upon entry and exit of your pIdle procedure, to make sure that the printer driver will image into the correct port during the print job.  Finally, if you are changing the resource chain by calling _OpenResFile or _UseResFIle, you want to make sure that you save and restore the resource chain. 
  1792. Further Reference:
  1793. •    Inside Macintosh, Volume II, The Printing Manager
  1794. •    Technical Note M.IM.PrintLoop —
  1795.          A Print Loop That Cares...
  1796. PR 23 - Position-Independent PostScript
  1797. Printing    
  1798. Revised by:        March 1988
  1799. Written by:    Scott "ZZ" Zimmerman
  1800. This technical note describes a method for inserting position-independent PostScript into QuickDraw pictures.
  1801. There is a problem with pictures that contain PostScript code. Sometimes the PostScript code that is inserted into the picture is dependent on the position of the picture on the page. The problem arises when these pictures are cut or copied from their original position, and pasted into another position or even into another document. The PostScript code will not know the new location of the picture, and will not execute correctly.
  1802. The solution for this problem, is to provide some way for the PostScript code to determine the current location of the picture relative to the page that it is being printed on. This is done by inserting QuickDraw calls to position the LaserWriter’s pen before inserting the position dependent PostScript code. When the PostScript in the picture is executed, the LaserWriter’s pen location will be in a location relative to the position of the picture on the page.
  1803. The following example illustrates a method for positioning the LaserWriter’s pen before inserting any PostScript code into the picture. The method uses QuickDraw calls to position the LaserWriter’s pen, and will work with any application that supports QuickDraw pictures. Applications do not have to be changed to be able to print pictures which use this technique; normal calls to DrawPicture will work.
  1804. The following code fragment will create a picture that contains PostScript to draw a rectangle around the picture’s frame:
  1805. FUNCTION CreatePicture(pictureRect: Rect): PicHandle; 
  1806.     CONST         
  1807.         PostScriptBegin = 190;         
  1808.         PostScriptEnd = 191;         
  1809.         PostScriptHandle = 192; 
  1810.     VAR         
  1811.         PSString     : Str255;         
  1812.         PSHandle     : Handle;         
  1813.         theError     : OSErr; 
  1814.     BEGIN         
  1815.         (* Create a new Picture. *)         
  1816.         CreatePicture := OpenPicture(pictureRect);                             ClipRect(pictureRect); 
  1817.         (* Set the pen size to 0,0 so the following Line will not *)
  1818.          (* be shown, it is only sent to position the pen.*)                         PenSize(0,0); 
  1819.         (* Move the QuickDraw pen to the first pixel inside the *)
  1820.         (* the picture’s frame.  This by itself will not *)
  1821.         (* change the LaserWriter’s pen location! *)     
  1822.         MoveTo(pictureRect.left, pictureRect.top);
  1823.  
  1824.         (* Force the LaserWriter’s pen location to match the  *)                     (* QuickDraw pen location.  Actually any drawing command, *)             
  1825.         (* such as LineTo or even DrawString will cause the *)
  1826.          (* LaserWriter’s pen location to change.  This call to *)                     (* the Line procedure only causes the coordinates of *)
  1827.          (* the above MoveTo to be flushed to the LaserWriter. *)                     (* Because of the PenSize call above, no Line is drawn. *)
  1828.          Line(0,0); 
  1829.         (* Reset the pen to its default size. *)         
  1830.         PenSize(1,1); 
  1831.         (* The LaserWriter’s pen location has now been changed.  The *)                 (* PostScript currentpoint operator will now return the *)
  1832.          (* location of the center pixel of the Picture. *) 
  1833.         (* Get the PostScript ready to be sent. *)             
  1834.         (* currentpoint        - push the current Point onto the stack. *)             (* newpath            - Begin a new Line segment. *)
  1835.          (* MoveTo            - Move to the currentpoint we saved above. *)             (* nn nn rlineto        - frame the Picture with lines. *)
  1836.          (* stroke             - Draw the frame. *)
  1837.          PSString := 
  1838.         '100 0 rlineto 0 100 rlineto -100 0 rlineto 0 -100 rlineto stroke '
  1839.                 ;
  1840.          PSString[length(PSString)] := CHR(13); (* Don’t forget CR. *)                     theError:=PtrToHand(Ptr(ORD4(@PSString)+1), 
  1841.                       PSHandle,length(PSString));
  1842.          IF theError <> noErr THEN HandleError; 
  1843.         (* Send the PostScript code to the LaserWriter. *)             PicComment(PostScriptBegin,0,nil);
  1844.             (* QuickDraw calls made between the PostScriptBegin *)
  1845.             (* and PostScriptEnd PicComments will be ignored by *)
  1846.             (* devices that support PostScript. *)
  1847.             PicComment(PostScriptHandle,GetHandleSize(PSHandle),PSHandle); 
  1848.         PicComment(PostScriptEnd,0,nil);
  1849.  
  1850.         (* Kill off the Handle we created and close the picture. *)
  1851.          DisposHandle(PSHandle); 
  1852.         ClosePicture;     
  1853.     END; (* CreatePicture *)
  1854. See the LaserWriter Reference Manual for more information about PicComments. See the PostScript Language Reference Manual for more information about the currentpoint operator.
  1855. There are some important guidelines to follow when sending PostScript directly to the LaserWriter. See the PostScript Commands section of Technical Note #91, for a complete description of these guidelines.
  1856. Further Reference:
  1857. •    The Print Manager
  1858. •    QuickDraw
  1859. •    LaserWriter Reference Manual
  1860. •    Technical Note M.IM.PictComments —
  1861.           Optimizing for the LaserWriter—PicComments
  1862. •    PostScript Language Reference Manual, Adobe Systems
  1863. •    PostScript Language Cookbook and Tutorial, Adobe Systems
  1864. PR 505 - PostScript Q&As
  1865. Printing    
  1866. Revised by:    Developer Support Center    September 1993
  1867. Written by:    Developer Support Center    October 1990
  1868. This Technical Note contains a collection of Q&As relating to a specific topic—questions you’ve sent the Developer Support Center (DSC) along with answers from the DSC engineers. While DSC engineers have checked the Q&A content for accuracy, the Q&A Technical Notes don’t have the editing and organization of other Technical Notes. The Q&A function is to get new technical information and updates to you quickly, saving the polish for when the information migrates into reference manuals.
  1869. Q&As are now included with Technical Notes to make access to technical updates easier for you. If you have comments or suggestions about Q&A content or distribution, please let us know by sending an AppleLink to DEVFEEDBACK. Apple Partners may send technical questions about Q&A content to DEVSUPPORT for resolution.
  1870. PostScript documentation
  1871. Date Written:  7/13/90
  1872. Last reviewed:  8/1/92
  1873. Adobe Systems publishes three great manuals that can help you with PostScript commands: PostScript Language Reference Manual, PostScript Language Tutorial, and PostScript Language Cookbook. You can find these manuals at just about any bookstore, or you can order them through APDA by calling (800) 282-2732 or writing them at:
  1874. Apple Computer, Inc.
  1875. 20525 Mariani Avenue, Mail Stop 33-G
  1876. Cupertino, CA 95014
  1877. AppleTalk packets and PostScriptHandle PicComment
  1878. Date Written:  8/7/90
  1879. Last reviewed:  8/1/92
  1880. What’s the optimal amount of PostScript to pass in PicComment 192 for AppleTalk packet throughput?
  1881. ___
  1882. There is no one optimal size that your PostScriptHandle PicComment should be for AppleTalk packets. The LaserWriter driver sends different amounts of PostScript, depending on the amount of memory that is available. It could send as little as 1K or as much as 4K bytes of PostScript at one time. The driver is using four 4096-byte buffers to send the data, and the amount of data that it sends from a particular buffer is completely memory dependent. In the general case, it does not send any data until a particular buffer is full. The driver does not control the number of packets that are sent over AppleTalk. When PAP receives the PostScript, it packages up the PostScript and sends it down to the LaserWriter.  In general, DTS recommends that applications send a PostScript handle that contains 4096 bytes of data.
  1883. Using PostScript to control LaserWriter serial I/O
  1884. Date Written:  12/6/90
  1885. Last reviewed:  3/28/93
  1886. Where can I find information on using PostScript to control a multi-tray sheet feeder by communicating through the LaserWriter serial port?
  1887. ___
  1888. You need to talk with Adobe on how they control the serial chip with PostScript. They use some undocumented PostScript calls to control the serial chip on the controller board of the LaserWriter. They can be reached at:
  1889.      Adobe Systems, Inc.
  1890.      1585 Charleston Road
  1891.      Mountain View, CA   94039
  1892. or
  1893.      AppleLink Address:  ADOBE.SUPT (Tech Support)
  1894. Details about installing feeder resources for Macintosh into the LaserWriter driver 7.0 dialogs are available in the Macintosh Technical Note “Feeder Fodder.”
  1895. How to inhibit LaserWriter test page
  1896. Date Written:  12/24/90
  1897. Last reviewed:  8/1/92
  1898. How do I inhibit the test page on a LaserWriter?
  1899. ___
  1900. 1. Use the LaserWriter Utility to turn the startup page off (best), or
  1901. 2. Download the following PostScript commands:
  1902. serverdict begin 0 exitserver
  1903. statusdict begin
  1904. false setdostartpage
  1905. end
  1906. The above commands can be downloaded from your Macintosh to the printer several ways:
  1907. 1. Use the menu command in the LaserWriter Utility that comes with System 7 (easiest).
  1908. 2. You can use a PostScript utility like LaserTalk from Emerald City Software.
  1909. 3. The PostScript Language facility in Microsoft Word.
  1910. 4. PSDump or PSsend
  1911. 5. Use the PostScript utilities in the Developer CD’s PostScript Utilities folder.
  1912. 6. Use the methods described in the Macintosh Technical Note #91.
  1913. When you issue the commands, your LaserWriter will probably crank and grind for a few seconds (it has to re-program the EPROM inside) then after the lights stop flashing, your LaserWriter will no longer spit out the startup page until you enable the setdostartpage flag again (in other words, this isn’t a permanent change).
  1914. For more information on the above subject we recommend the PostScript Language Reference Manual by Adobe Systems.
  1915. Where to find Encapsulated PostScript file (EPSF) documentation
  1916. Date Written:  4/5/91
  1917. Last reviewed:  8/1/92
  1918. I’m developing an application that creates pictures containing both QuickDraw and PostScript (as picComments). How do I create an encapsulated PostScript file (EPSF)? Is the format explained anywhere, and is it possible to convert the QuickDraw into PostScript directly in the application?
  1919. ___
  1920. Adobe’s EPSF format is documented in the new (2nd) edition of Adobe’s PostScript Language Reference Manual (Addison-Wesley) and in “Adobe Document Structuring Conventions,” available from Adobe Systems. Adobe’s  references explain how to structure your comments in your PostScript file so that other applications know how to read it.
  1921. You probably don’t want to try to convert QuickDraw to PostScript directly in your application, although it is possible. Basically, it involves translating each QuickDraw command into PostScript, which is what the LaserWriter Driver does. It’s a lot of work and makes you dependent on the QuickDraw features being used, which can be a problem when new features are added.
  1922. PostScript setprintername doesn’t accept colons in string
  1923. Date Written:  4/16/91
  1924. Last reviewed:  8/1/92
  1925. Why can’t I use a colon with the PostScript command setprintername to change the Personal LaserWriter NT network name and type, but it works with the LaserWriter II?
  1926. ___
  1927. The reason that the Personal LaserWriter NT is not accepting the PostScript you’re sending is not because of a bug, but rather a bug fix. Colons have never been acceptable in the string passed to setprintername. (See page 296 of Adobe’s PostScript Language Reference Manual.) The reason the call works in older LaserWriters but not the Personal LaserWriter NT is that the NT has a newer version of PostScript in it. Older versions of PostScript didn’t enforce Adobe’s printer naming conventions. The setprintername restrictions have been enforced in more recent versions, however. Therefore, colons are not allowed.
  1928. If you need to change the LaserWriter network type, it can be done with the AppleTalk-type parameter described on page 105 of Apple’s LaserWriter Reference manual. This method will work on the new printers as well as the old.
  1929. PostScript code for renaming LaserWriter
  1930. Date Written:  6/5/91
  1931. Last reviewed:  8/1/92
  1932. In checking a printer name to ensure an even number of characters, does the LaserWriter Namer append a space to the end if the total is odd?
  1933. ___
  1934. In a nutshell, yes. The Namer does indeed append an extra space to odd-length printer names. The reasoning behind this is to be compatible with some of the old 68000 processors. The addressing scheme of these old processors requires that memory be accessed by even-numbered addresses. To get at a piece of memory located after an odd-length LaserWriter name, you would need to get an odd-numbered address (which is not directly possible). This obviously can be worked around, but the authors of the Namer felt it best to avoid this altogether by padding the name when necessary. It’s worth noting that the version 7.0 Namer does this too.
  1935. If you’d like to work around this, here’s an alternate method for renaming the printer:
  1936. The printer name is stored as a string in the persistent parameters of all LaserWriters. This string can be changed by the following PostScript program:
  1937.     serverdict begin 0 exitserver
  1938.     statusdict begin (NEWNAME) setprintername
  1939. Replace NEWNAME with the name you want for the printer. The name can be up to 31 characters and should consist entirely of printing characters--the “@” and “:” cannot be used. Note that parentheses are required.
  1940. This program can be downloaded to the LaserWriter in batch or interactive mode. In interactive mode you should type both command strings on the same line before pressing Enter, because exitserver disconnects you from the printer. When you reestablish your connection to the printer, the name will be changed.
  1941. Make sure you have selected the correct LaserWriter using the Chooser before downloading this program, so you don’t rename the wrong LaserWriter.
  1942. Printing 2-byte bitmap fonts on PostScript LaserWriters
  1943. Date Written:  9/29/91
  1944. Last reviewed:  8/1/92
  1945. The Macintosh Technical Note #91 refers to using QuickDraw picComments to print rotated text, but this doesn’t work for 2-byte Japanese text. Is there a recommended workaround for this problem?
  1946. ___
  1947. Two-byte characters don’t print when using the TextBegin, TextCenter, and TextEnd PicComments because of the structure of the data that is being sent in the comments. The LaserWriter driver uses these PicComments to rotate text, and it is not expecting the data to be in the 2-byte format. The 2-byte format is converted to bitmap data by the driver, so the data is ignored and nothing is printed. The driver is expecting the comments to contain “normal” text.
  1948. Since the data is in bitmap format, you can use the RotateBegin and RotateEnd PicComments to perform the rotation, as follows:
  1949. RotateBegin
  1950.     DrawString (...);  << To rotate your 2 byte Japanese characters
  1951. RotateEnd
  1952. The tricky part of the solution is that you only need to use this approach when you’re printing 2-byte Japanese bitmap fonts. Therefore, you’ll need to check the type of data that is to be printed, and send the appropriate PicComments.
  1953. You can also use the following PicComments to hide the QuickDraw representation of the rotated text, as shown below:
  1954. PostScriptBegin
  1955.     CopyBits (...);   << For the QuickDraw printers
  1956. PostScriptEnd
  1957. The PostScriptBegin and PostScriptEnd PicComments are used to hide the CopyBits calls from the LaserWriter driver in a device-independent manner. When you use PostScriptBegin, the LaserWriter driver doesn’t interpret any QuickDraw calls until it finds the PostScriptEnd PicComment. Since QuickDraw printer drivers do not understand the PostScriptBegin and PostScriptEnd PicComments, they ignore the PicComments, and the CopyBits call is used to perform the rotation of your text.
  1958. There is one problem with the previously mentioned solution: If you record the previous PicComments into a picture and print it, everything will print exactly as expected, but if you display the picture into a window, you’ll see the unrotated version of the text. This is definitely a bug, which has been reported, but it won’t be fixed in the very near future. So, what do you do in the meantime? You have the following two options:
  1959. 1) Do not export pictures that contain this type of rotated data.
  1960. 2) Export the picture with this problem, and explain the problem to your users.
  1961. Neither solution is ideal. Quite a few applications out in the market today have decided to use idea #2.
  1962. Macintosh spooling should be device independent
  1963. Date Written:  1/1/90
  1964. Last reviewed:  8/1/92
  1965. How can I tell whether the chosen printer supports PostScript or not?
  1966. ___
  1967. There is no supported method for determining whether or not a device speaks PostScript. Apple engineering would like all Macintosh applications to spool both PostScript and QuickDraw regardless of the chosen printer, so that the spool file is device-independent and can be redirected after spooling. Since engineering is strongly encouraging developers to spool both models, it is doubtful that Apple will be providing a query mechanism in the future. The best method is to assume PostScript is available, and format your document based on information returned by PrGeneral and the print record.
  1968. LaserWriter driver and PostScript showpage
  1969. Date Written:  1/1/90
  1970. Last reviewed:  6/14/93
  1971. When I print a PostScript file, why do I get one blank page for every page printed?
  1972. ___
  1973. Your PostScript file probably contains calls to the PostScript showpage operator. This operator is also called by the Macintosh LaserWriter driver when it receives the PrClosePage call. The solution to this problem is to strip showpage calls from the file before sending the file to the LaserWriter. If you send one QuickDraw graphic at the beginning of each page,
  1974.     MoveTo(-32000, -32000);
  1975.     Line(0, 0);
  1976. the LaserWriter driver will handle calling showpage for you. Versions of the LaserWriter driver before 5.2 do not send the showpage operator unless a QuickDraw drawing routine (that is, something other than PicComment) is sent. This is why you need to do the MoveTo/LineTo. Versions 5.2 and later will send the showpage operator whether any QuickDraw has been sent or not. Since you can’t be sure whether showpage will be sent for you or not, the best solution is to let the LaserWriter driver send it.
  1977. PicComment TextIsPostScript versus PostScriptHandle
  1978. Date Written:  1/1/90
  1979. Last reviewed:  6/14/93
  1980. When using the Macintosh TextIsPostScript picture comment, my PostScript code is also “printed” on the ImageWriter. Why isn’t it ignored?
  1981. ___
  1982. One of the comments, TextIsPostScript, allows the application to use the QuickDraw DrawString procedure to send the PostScript code. This method is no longer recommended, as it is not device independent. If you use the TextIsPostScript comment when printing to a non-PostScript device, the PostScript code will be printed as text. On an ImageWriter, the entire PostScript program will be printed as one line on the page, because the TextIsPostScript PicComment is ignored by the ImageWriter drivers, and the DrawString calls are executed normally.
  1983. To avoid this problem, developers should use the PostScriptHandle comment. This comment accepts a handle as a parameter. The handle points to the PostScript code that you want to download. This comment is better for two reasons:
  1984. First, there is no QuickDraw/PostScript interaction. For example, early versions of the LaserWriter driver sent the strings passed to DrawString as-is. The latest version of the driver appends carriage returns onto those strings. If your application is expecting the DrawString calls to work one way or another, you might get a surprise.
  1985. The other reason for using the PostScriptHandle comment involves device independence. When a non-PostScript driver sees the PostScriptHandle PicComment, it not only ignores the comment, but also ignores the PostScript data that was passed to the comment, so nothing prints if you use the PostScriptHandle comment on a non-PostScript driver.
  1986. X-Ref:
  1987. Macintosh Technical Note  “How To Produce Continuous Sound Without Clicking”
  1988. How to send PostScript from the Macintosh to the LaserWriter
  1989. Date Written:  5/3/89
  1990. Last reviewed:  6/14/93
  1991. How do I send PostScript from the Macintosh to the LaserWriter?
  1992. ___
  1993. The best method for sending PostScript to the LaserWriter is to use the PostScriptHandle (kind = 192) PicComment documented in the Macintosh Technical Notes “Optimizing for the LaserWriter” and “Picture Comments—the Real Deal.” There are a few PicComments for sending PostScript to the LaserWriter, but the easiest to use and most problem free is the PostScriptHandle comment. One model is:
  1994.  PrOpenPage(...)
  1995.  { Send some QuickDraw so that the Printing Manager gets a  }
  1996.  { chance to define the clip region.             }
  1997.  MoveTo(-32000, -32000);
  1998.  Line(0, 0);
  1999.  PicComment(PostScriptBegin, 0, NIL);
  2000.  { QuickDraw representation of graphic. }
  2001.  MoveTo(100, 100);
  2002.  LineTo(200, 200);
  2003.  { PostScript representation of graphic. }
  2004.  thePSHandle^^ := '100 100 moveto 200 200 lineto stroke';
  2005.  PicComment(PostScriptHandle,GetHandleSize(thePSHandle),thePSHandle);
  2006.  PicComment(PostScriptEnd, 0, NIL);
  2007.  PrClosePage(...)
  2008. The described fragment prints a line on any type of printer, PostScript or not. The first MoveTo/Line combination is required to give the LaserWriter driver a chance to define a clipping region. The LaserWriter driver replaces the grafProcs record in the GrafPort returned from PrOpenDoc. In order for the LaserWriter driver to get execution time, you must execute a QuickDraw drawing routine that calls one of the grafProcs. In this case, the MoveTo/Line combination is sent firing the StdLine grafProc. When StdLine executes, it notices that the GrafPort has been reinitialized, and therefore initializes the clipping region for the port. Until the MoveTo/Line combination is executed, the clipping region for the port is set to (0,0,0,0). If PostScript code is sent via the PostScriptHandle PicComment before executing any QuickDraw routines, all PostScript operations will be clipped to (0,0,0,0). The next thing to do is send the PostScriptBegin PicComment. This comment is recognized only by PostScript printer drivers. When the driver receives this comment, it saves the current state of the PostScript device (by executing the PostScript gsave operator), then disables all QuickDraw drawing operations. This way, the QuickDraw representation of the Graphic will be ignored by PostScript devices. In the previous example, the MoveTo/LineTo combination is only executed on non-PostScript devices. The next comment is the PostScriptHandle PicComment. This tells the driver that the data in thePSHandle is to be sent to the device as PostScript code. The driver then passes this code unchanged to the PostScript device for execution. The PostScriptHandle PicComment is only recognized by PostScript printer drivers. The last PicComment, PostScriptEnd, tells the driver to restore the previous state of the device (via a PostScript grestore call), and to enable QuickDraw drawing operations. Since all PicComments are ignored by QuickDraw devices, only the QuickDraw representation is printed. Since PostScriptBegin tells PostScript drivers to ignore QuickDraw operations, only the PostScript representation is printed on PostScript devices. This is a truly device-independent method for providing both PostScript and QuickDraw representations of a document.
  2009. Converting PostScript file to Encapsulated PostScript
  2010. Date Written:  5/19/92
  2011. Last reviewed:  6/14/93
  2012. What needs to be added to an ordinary PostScript file to convert it to an Encapsulated PostScript (EPS) file?
  2013. ___
  2014. The latest Adobe “red book,” PostScript Language Reference Manual (2nd Edition), has the information you need. Appendix H: Encapsulated PostScript File Format Version 3.0 describes the contents of an EPS file. Appendix G: Document Structuring Conventions specifies the single-page document PS file, which must include at least these two comments:
  2015.     %!PS-Adobe-3.0 EPSF-3.0
  2016.     %%BoundingBox: llx lly urx ury
  2017. You might find the following references from Adobe useful as well:
  2018.     Adobe Illustrator Document Format Specification v2.0 (Adobe Technical Note #LPS5007)
  2019.     Encapsulated PostScript Files v1.2 (Adobe Technical Note #LPS5002)
  2020. You can reach Adobe at:
  2021.     Corporate Headquarters
  2022.     1585 Charleston Road, PO Box 7900
  2023.     Mountain View, CA 94039-7900
  2024.     (415) 961-4111 Developer Support
  2025. Macintosh Technical Note “Picture Comments—The Real Deal” (formerly #91) contains sample code for using all of the supported Picture Comments.
  2026. Printing halftone images on the LaserWriter
  2027. Date Written:  5/3/89
  2028. Last reviewed:  8/1/92
  2029. How can I print halftone images on the LaserWriter? How do I use the PostScript “image” operator for printing halftones?
  2030. ___
  2031. The PostScript “image” operator is similar to the Macintosh QuickDraw CopyBits routine. It can be used by converting a QuickDraw bitmap/pixmap into an image call. This is only necessary if you are printing color information with a PostScript printer driver that doesn’t support Color QuickDraw. LaserWriter drivers up to 5.2 do NOT support Color QuickDraw. If you want to send color information to a LaserWriter with version 5.2 of the driver, you will have to convert your color images into image commands. Before doing this it is important to check the GrafPort returned by PrOpenDoc. If this port is a Color QuickDraw port (for example, portBits.rowBytes < 0) then you should use Color QuickDraw commands and let the driver handle the conversion to PostScript.
  2032. About image: The PostScript image operator is used to send bitmaps or pixmaps to the LaserWriter. The image operator can handle depths from one to eight bits per pixel. Our current LaserWriters can image only about 16 shades of gray, but the printed page will look like there’s more. Because the image operator is still a PostScript operator, it expects its data in the form of hexadecimal bytes. The bytes are represented by two ASCII characters(“0”-”9,” “A”-”F”) per byte. The image operator takes these parameters: width height depth matrix image-data
  2033. The first three are the width, height, and depth of the image, and the matrix is the transformation matrix to be applied to the current matrix. See the PostScript Language Reference Manual for more information. The image data is where the actual hex data should go. Instead of inserting the data between the first parameters and the image operator itself, it is better to use a small PostScript procedure to read the data starting right after the image operator. For example:
  2034. 640 480 8 [640 0 0 480 0 0] {currentfile picstr readhexstring pop} image FF 00
  2035. FF 00 FF 00 FF 00...
  2036. In the preceding example, the width of the image is 640, the height is 480, and the depth is 8. The matrix (enclosed in brackets) is set up to draw the image starting at QuickDraw’s 0,0(top left of page), and with no scaling. The PostScript code (enclosed in braces) is not executed. Instead, it is passed to the image operator, and the image operator calls it repeatedly until it has enough data to draw the image. In this case, it is expecting 640*480 bytes. When the image operator calls the procedure, it does the following:
  2037. 1.    Pushes the current file which in this case is the stream of data coming to the LaserWriter over AppleTalk. This is the first parameter to the readhexstring operator.
  2038. 2.    Pushes picstr. picstr is a string variable defined to hold one row of hex data. The PostScript to create the picstr is:
  2039.     /picstr 640 def
  2040. 3.    readhexstring is called to fill picstr with data from the current file. It begins reading bytes which are the characters following the image operator.
  2041. 4.    readhexstring leaves the string we want, and a boolean that we don’t want, on the stack, so we do one pop to kill off the boolean. Now the string is left behind for the image operator to use.
  2042. Using the above PostScript code you can easily print an image. Just fill in the width height and depth, and send the hex data immediately following the PostScript code.
  2043. Setting up for image: Most of the users of this technique are going to want to print a Color QuickDraw pixmap. Although the image command does a lot of the work for you, there are still a couple of tricks for performance:
  2044. Assume the maximum depth: Since the current version of the image operator has a maximum depth of eight bits/pixel, it is wise to convert the source image to the same depth before imaging. You can do this very simply by using an offscreen GrafPort that is set to eight bits/pixel, and then using CopyBits to do the depth conversion for you. This does a nice job of converting lower resolution images to 8 bits/pixel.
  2045. Build a color table: An eight bit deep image can use only 256 colors. Since the image that you are starting with is probably color, and the image you get will be grayscale, you need to convert the colors in the source color table into PostScript grayscale values. This is actually easy to do using the Color Manager. First create a table that can hold 512 bytes. This is two bytes for each color value from 0 to 255. Since PostScript wants the values in ASCII, you need two characters for each pixel. Now loop through the colors in the color table. Call Index2Color to get the real RGB color for that index, and then call RGB2HSL to convert the RGB color into a luminance value. This value is expressed as a SmallFract which can then be scaled into a value from 0 to 255. This value should then be converted to ASCII, and stored at the appropriate location in the table. When you are done, you should be able to use a pixel value as an index into your table of PostScript color values. For each pixel in the image, send two characters to the LaserWriter.
  2046. Sending the data: Once you have set up the color table, all that’s left to do is loop through all of the pixels, and send their PostScript representation to the LaserWriter. There are a couple of ways to do this. One is to use the low-level Print Manager interface and stream the PostScript using the stdBuf PrCtlCall. Although this seems like it would be the fastest way, the latest version of the LaserWriter driver (5.0) converts all low-level calls to their high level equivalent before executing them, so the low-level interface is no longer faster than the high level. Another way is to use the high-level Print Manager interface, and send the data via the PostScriptHandle PicComment. This enables you to buffer a large amount of data before actually sending it. Using this second technique, you should be able to image a Macintosh II screen in about 5 minutes on a LaserWriter Plus, and about 1.5 minutes on a LaserWriter II NTX.
  2047. X-Ref:
  2048. PostScript Language Reference Manual, Adobe Systems.
  2049. PR 510 - Printer Driver Q&As
  2050. Printing    
  2051. Revised by:    Developer Support Center    September 1993
  2052. Written by:    Developer Support Center    October 1990
  2053. This Technical Note contains a collection of Q&As relating to a specific topic—questions you’ve sent the Developer Support Center (DSC) along with answers from the DSC engineers. While DSC engineers have checked the Q&A content for accuracy, the Q&A Technical Notes don’t have the editing and organization of other Technical Notes. The Q&A function is to get new technical information and updates to you quickly, saving the polish for when the information migrates into reference manuals.
  2054. Q&As are now included with Technical Notes to make access to technical updates easier for you. If you have comments or suggestions about Q&A content or distribution, please let us know by sending an AppleLink to DEVFEEDBACK. Apple Partners may send technical questions about Q&A content to DEVSUPPORT for resolution.
  2055. New Q&As in this Technical Note:
  2056. Defining default LaserWriter Pro paper tray
  2057. Code for getting selected printer name
  2058. StyleWriter II driver differences
  2059. Determining printer font
  2060. Defining default LaserWriter Pro paper tray
  2061. Date Written:   5/17/93
  2062. Last reviewed: 5/19/93
  2063. How can I set the default paper tray on my LaserWriter Pro to something other than the 250-sheet cassette?
  2064. ___
  2065. The paper tray selection in the printing job dialog is not “sticky”; it’s not preserved from job to job. In LaserWriter 7.2, the choice of one of the two paper trays is stored in the print record. You may be able to hack out where this is stored and define a new “default” print record by changing the PREC(0) resource, but this is completely unsupported and you do so at your own risk.
  2066. In LaserWriter driver 8.0, the default paper trays are defined in the PostScript Printer Definition (PPD) file.  If you’re sufficiently adventurous, you can edit the PPD file for your printer to change these relationships.  LaserWriter 8.0 requires files that meet the PPD 4.0 specification, available from Adobe’s Developer Support program.
  2067. Code for getting selected printer name
  2068. Date Written:   3/10/93
  2069. Last reviewed: 6/24/93
  2070. How do I get the name of the currently selected printer, for Systems 6 and 7?
  2071. ___
  2072. The printer driver has a resource of type PAPA, ID -8192, which contains the name of the selected printer and the network object type. This resource is amazingly easy to get; you don’t even need to know where the printer driver resource file is located. Just call PrOpen. The Printing Manager will open the currently selected printer driver for you, and place it at the top of the resource chain. Then see whether you can GetResource for 'PAPA' ID -8192, and viola—you have a handle to the printer name.
  2073. This will work under both System 6 and System 7. However, under QuickDraw GX, this method is subject to change. Also note that this is a read-only field; changing it doesn’t necessarily change the selected printer.
  2074. The printer name is the first string, and the object type is packed right up against it. If all you want is the name, then here’s a C routine that will provide it:
  2075. OSErr GetPrinterName(Str255 prName)
  2076. {
  2077.   OSErr   err = noErr;
  2078.   char  **papaDataHandle;
  2079.   PrOpen();
  2080.   papaDataHandle = Get1Resource('PAPA',-8192);
  2081.   if(!papaDataHandle) {
  2082.     err = ResError();
  2083.   } else {
  2084.     BlockMove(*papaDataHandle, prName, (**papaDataHandle)+1);
  2085.     ReleaseResource((Handle) papaDataHandle);
  2086.   }
  2087.   PrClose();
  2088.   return err;
  2089. }
  2090. StyleWriter II driver differences
  2091. Date Written:   3/17/93
  2092. Last reviewed: 6/24/93
  2093. My application won’t print to a StyleWriter II although it works fine on all other printers including the original StyleWriter. Can you give me any suggestions? What’s different about the StyleWriter II?
  2094. ___
  2095. The StyleWriter II driver is a member of the “GrayShare” driver family, with new features such as support for grayscale printing (if Color QuickDraw is available) and printer sharing over the network. Its internal architecture is very different from previous printer drivers. In spite of thorough compatibility testing, some problems have shown up since the first release. In many cases, the driver revealed weaknesses in the applications themselves; for some other problems, a solution will be incorporated in the next release of the driver. Here are currently identified problem areas with the StyleWriter II driver:
  2096. •    The StyleWriter II driver handles memory differently. For example, if an application has a dereferenced handle to an unlocked block while CopyBits’ing into the printing port, this may work fine on all other printer drivers, but the block is likely to move with the StyleWriter II driver, and the results are unpredictable.
  2097. •    The StyleWriter II driver maintains its own A5 world internally. If an application installs a growZone proc and forgets to set up its own A5 in the growZone proc (ignoring the Technical Note “Register A5 Within GrowZone Functions”), the growZone proc may get called with the StyleWriter II driver’s A5, which obviously is bad for the survival of both the application and the printer driver.
  2098. •    The StyleWriter II driver calls the pIdleProc (in the job subrecord of the print record) more often than other printer drivers; in particular, it may be called during execution of PrOpenDoc. If an application reloads a print record previously used, containing an old (now invalid) pointer to an idleProc, and doesn’t update the pIdleProc field before calling PrOpenDoc, disaster is very likely. Note that the TechNote “pIdle Proc (or how to let users know what’s going on during print time)” recommends installing the idleProc before PrOpenDoc.
  2099. •    Like most other QuickDraw printer drivers, the StyleWriter II driver uses algorithms built into QuickDraw for rasterizing picture elements like ovals and arcs, but not necessarily with the same sequence of coordinate transformations. Because of the 360 dpi resolution, internal computations with the transformed coordinates may hit the 16-bit integer limitation of QuickDraw, and reveal bugs in the old QuickDraw routines that have never been discovered so far. 
  2100. •    The StyleWriter II driver (version 1.0) contains STR# resources with positive ID numbers that may conflict with STR# resources in an application. This will be fixed in the next release of the driver.
  2101. •    Under certain circumstances, the StyleWriter II driver seems to have trouble with a PmForeColor call. This is under investigation and will be fixed.
  2102. Determining printer font
  2103. Date written: 1/26/93
  2104. Last reviewed: 4/26/93
  2105. Our application must print with Helvetica if available, and Geneva if not. How can I determine which fonts are available in a printer? I’ve been using the wDev field in the print record and assuming that a value of 3 means Helvetica will print correctly, but according to “Print Hints: Top 10 Printing Misdemeanors” in develop issue 12, this isn’t dependable.
  2106. ___
  2107. There’s no procedural way to ask a printer if it even has built-in fonts, let alone what they are. By using wDev == 3, you’ve been assuming that all PostScript printers have built-in Helvetica fonts, and while most do, some do not. There are several things you can do, though.
  2108. First of all, you should know about font substitution. If this option is checked in the LaserWriter driver (it’s checked by default), you’ll get Helvetica instead of Geneva when drawing in Geneva on PostScript printers that have Helvetica. The driver adjusts all the font metrics so the widths match what you see on the screen. In some versions of the LaserWriter driver, you’ll get Geneva instead—but only if the Geneva TrueType font is available, so you get excellent quality either way. This might be enough to solve your entire problem.
  2109. If not, there’s the new PSWriter driver on AppleLink and on the Developer CD Series disc. PSWriter uses PostScript Printer Definition (PPD) files and supports a new PrGeneral call that lets you obtain the PPD file so that you can know things about your target printer, including what fonts are installed. While this might give misleading results if the user has never set up the printer (and is using the Generic PPD), it should be just fine in all other cases.
  2110. There’s no way to tell whether the user has downloaded a font to the PostScript printer, making it available, because it won’t be in the PPD file and there’s no way to ask the printer.
  2111. Where to get PostScript Printer Definition (PPD) files
  2112. Date written:  2/9/93
  2113. Last reviewed:  4/1/93
  2114. Where can I get PostScript Printer Definition (PPD) files for Apple’s PostScript printers?
  2115. ___
  2116. Apple recently made PPD files for its printers—past and present—available. You can find them on AppleLink in the Software Sampler: Apple SW Updates: Macintosh: Printing Software: PPDs folder.
  2117. PPD files for non-Apple PostScript printers with ROMs by Adobe Systems are available from a clearinghouse maintained by Adobe. To request a PPD file from Adobe, send an internet message to “ps-file-server@adobe.com” with the subject “help”. Adobe’s list server will respond with mail about items available on the list server and how you can get them.
  2118. LaserWriter Driver 7.2 isn’t ColorSync aware
  2119. Date written:  1/11/93
  2120. Last reviewed:  4/1/93
  2121. Is LaserWriter Driver 7.2 ColorSync aware?
  2122. ___
  2123. No, LaserWriter Driver 7.2 isn’t ColorSync aware. Apple plans to add ColorSync capability to future versions of the LaserWriter driver, but we don’t have any more information or details than that.
  2124. Printing nonstandard page dimensions
  2125. Date written:  1/14/93
  2126. Last reviewed:  6/14/93
  2127. How do we override the standard page dimensions for the StyleWriter or, for that matter, any other printer? We want to print 5.5" x 8.5" (half letter-sized) pages.
  2128. ___
  2129. The current printing architecture isn’t designed for elegant (or sometimes any) communication from your program to the printer driver. All the calls you normally make (such as PrOpenDoc, PrOpenPage, and PrPicFile) are handled by the printer driver and not by the Printing Manager. The drivers manage the print records, put up the dialog boxes, decide how to render graphics and everything else in between. That’s why writing a printer driver is so hard.
  2130. If you want to tell a printer driver “I want to use this size paper,” that driver has to implement a driver-specific way to do it or it can’t be done. There’s no PrSetPageSize call in the current printing architecture. In fact, trying to print outside the rPage rectangle can cause physical damage on some printers, so customizing page sizes is not something you want to enter into lightly.
  2131. You can’t change the paper size in the print record, because most drivers don’t look there to see what size you want; instead they tell you what size you get in that field. The same is true for most of the print record: Unless Inside Macintosh tells you that you can write to that field, you can’t (or doing so won’t do any good).
  2132. The StyleWriter in particular has very limited paper options; it handles letter, legal, A4, and B5 paper sizes—and that’s it. If you try to print other sizes, the hardware reports an error. This is pretty common in these days of very low-cost high-quality printers; features that you as a programmer would want are jettisoned to keep the cost down. Most low-cost laser printers have limited paper-handling capabilities as well. If you try to print continuous feed paper on a StyleWriter, you’ll get a paper jam error after about 15 inches of paper pass through (long enough for the printer to realize it’s not legal-sized paper). Your half-letter size pages are too short for the printer to use.
  2133. While QuickDraw GX has a much more robust printing architecture, that doesn’t help right now for the current world. Something that you may wish to consider is making forms available on regular letter-sized paper, with two per sheet. That size paper works in every printer sold in the United States and could be perforated and detached by the customers.
  2134. All of Apple’s LaserWriter printers have excellent paper handling but cost relatively more. The best way to handle custom page printing across all printers is to place your custom-sized image on an 8.5" x 11" page and provide special paper.
  2135. Many, but not all, of Apple’s printers support a PREC 3 resource that contains extra page sizes in a custom format. The format of this resource is as follows:
  2136.  PageSizeRecord = RECORD
  2137.   numItems: INTEGER;
  2138.   botRights: ARRAY [0..NumPageOptionsZB] OF Point;
  2139.   titles: PACKED ARRAY [0..0] OF CHAR;
  2140.  END;
  2141. numItems is the number of page sizes displayed in the dialog. The maximum number is six (since there is only room for six radio buttons in the Page Setup dialog). botRights is an array of points specifying the bottom right corner for each page. This corner is specified in 120ths of an inch, and it should define the physical size of the paper, not the imageable area. For example, U.S. Letter is specified as:
  2142.     bottom = 1320(11"), right = 1020(8.5"). 
  2143. titles is a packed array of page size names. Each name begins with a length byte, followed by the number of characters specified by the length byte. The strings are packed, so string1[LENGTH(string1)+1] would reference the length byte of string2. 
  2144. To use this mechanism, your application should create a PREC resource with an ID = 4. You can do this very easily by copying PREC(3). Once you have a copy, you can modify the page sizes as you wish. When the printer driver is called to display the Page Setup dialog, it will first look for PREC(4). If found, it will use it to define the page sizes. If not found, the driver will use the standard sizes in PREC(3).
  2145. This method only works with some of Apple’s drivers; the LaserWriter driver ignores these resources. If you decide to implement this feature in your application, be sure to warn your users that custom page sizes may not be available on all devices.
  2146. Use this feature at your own risk; it’s very likely not to work under QuickDraw GX and later system software.
  2147. LaserWriter driver 'feed' resource troubleshooting
  2148. Date written:  11/24/92
  2149. Last reviewed:  3/1/93
  2150. The userdict definitions in my LaserWriter driver 'feed' resource (written per the Macintosh Technical Note “Feeder Fodder”) get wiped out after each page. At least, every time my redefined showpage is executed the variables that should have been defined the first time in userdict are unbound. What could be happening here? How should I define something in 'feed' resource code that acts like a global variable for a redefined showpage?
  2151. ___
  2152. Your operators shouldn’t be wiped out with each page. You’re being loaded before the PREC 103 is loaded and before the series of save and restore operators are called, which could otherwise wipe you out. Please read the Macintosh Technical Note “The Lo Down on Dictionary Downloading” for a robust description of this process. Thus, we must look to other reasons why your operators are being wiped out.
  2153. The natural culprit is your PostScript. Are you wiping yourself out? Second, you should heed the warning on page 4 of the “Feeder Fodder” Technical Note: “As always, calling or redefining operators defined by the LaserPrep (md) dictionary isn’t supported.” You could see problems as you describe if you’re redefining LaserPrep dictionary commands. Other variables include the system software and LaserWriter driver versions that you’re using. It could be an issue with the type of LaserWriter itself.
  2154. LaserWriter driver doesn’t SwapMMUMode for 32-bit addresses
  2155. Date written:  11/17/92
  2156. Last reviewed:  6/14/93
  2157. When I use CopyBits to move a cGrafPort’s portPixMap to another cGrafPort (my printing port), it works like a charm when background printing is turned on, but when CopyBits gets called with background printing turned off, the image that prints isn’t the image at all. Why is this happening?
  2158. ___
  2159. You should be aware that since you’re copying the pixels directly from the screen, the baseAddr pointer for the screen’s pixMap may be 32-bit addressed. In fact, with 32-Bit QuickDraw, this is the case. This in itself isn’t a problem, since CopyBits knows enough to access the port’s pixMap’s baseAddr in 32-bit mode, as follows:
  2160. mode = true32b;
  2161. SwapMMUMode(&mode);  // Make sure we're in 32-bit addressing mode.
  2162. // Access pixels directly; make no other system calls.
  2163. SwapMMUMode(&mode);  // Restore the current mode.
  2164. That’s how you’d normally handle things if you were accessing the pixels directly yourself. Unfortunately, the LaserWriter driver doesn’t know enough to do the SwapMMUMode and instead ends up copying garbage (from a 32-bit pointer stripped to a 24-bit pointer).
  2165. So why does background printing work? Because when you print in the background, everything is rolled into a PICT, which the driver saves off for PrintMonitor. Since the driver is using the standard QuickDraw picture bottlenecks to do this, and CopyBits knows to swap the MMU mode before copying the data into the picture, everything works great. Later, at PrintMonitor time, the picture is played back. Since the data is no longer 32-bit addressed, the LaserWriter driver doesn’t have to call SwapMMUMode to do the right thing; it can just play the picture back.
  2166. The solution we propose for you is something similar. At print time (before your PrOpenPage call), call OpenPicture, copy the data from the screen with CopyBits, call ClosePicture, and then call DrawPicture within your PrOpenPage/PrClosePage loop. That should do the trick.
  2167. Note that copying bits directly from the screen is not something we recommend. Unless you have no alternative, you should always copy from the original source of the data instead.
  2168. System 7.1 and printer driver compatibility
  2169. Date written:  11/18/92
  2170. Last reviewed:  6/14/93
  2171. If a user upgrades from System 7.0.x to 7.1, a new version of the PrintMonitor is installed. Will existing printer drivers behave correctly with the new PrintMonitor?
  2172. ___
  2173. When a user installs System 7.1, Easy Install will update any existing printer software. If the user picks Customize, he or she must choose the printers to be updated. Only the versions of the printer drivers that come with System 7.1 should be used with 7.1. Mixing and matching is bad.
  2174. Since only Apple’s printer drivers use PrintMonitor, as long as you upgrade to System 7.1 by using the Installer there’s no issue at all.
  2175. System 6 and System 7 PrintMonitor
  2176. Date written:  11/18/92
  2177. Last reviewed:  3/1/93
  2178. Is the version of PrintMonitor that ships with System 7.1 compatible with System 6? If so, which version of the Backgrounder file would be compatible for installation with the System 7.1 PrintMonitor on System 6.x systems?
  2179. ___
  2180. Only Apple’s printer drivers should be using PrintMonitor—the interface is undocumented and unsupported for other printer drivers. PrintMonitor-like things are a different story, but the specific Apple product PrintMonitor works only with Apple’s printer drivers.
  2181. While the drivers may be used under System 6, users should use the versions of Backgrounder and PrintMonitor present on the System 6.0.8 disks. Since Backgrounder and PrintMonitor are tied together, we have to recommend against using the 7.1 PrintMonitor under System 6.
  2182. Note that in all these cases, nothing was specifically added to make things not work under System 6—they simply weren’t tested and therefore can’t be supported.
  2183. Summary:
  2184. System 6: Backgrounder and PrintMonitor from 6.0.8, current driver
  2185. System 7: Use whatever the Installer installs.
  2186. Which printers to test printing
  2187. Date written:  10/1/92
  2188. Last reviewed:  11/2/92
  2189. We need to know what printers on which to test our application. It prints only pixmaps. It’s been tested on some LaserWriters. The question is, how many brands and models of printers do we need to test it on? Are there any definitive printing tests (for example, does success on a LaserWriter indicate correctness of the application)?
  2190. ___
  2191. Unfortunately, there is no such thing as a universal printing test suite. Moreover, successful printing not only depends on the specific printer driver (and its version), but also on the available memory at print time, and on things like the font configuration in the system. (Given that you print pixmaps only, the last comment is not applicable. Most certainly, all potential problems will rather boil down to out of memory conditions). Also, we have seen applications with severe defects in their printing code print quite correctly to the LaserWriter, and fail only on a few other specific printers. Most other printing problems have to do with assumptions about the inner working of a specific printer driver, such as hacking the print record behind the back of the Printing Manager. In this case, trouble with at least one of the 150 plus different printer drivers out there is guaranteed!
  2192. Pragmatically speaking, you may want to test printing in priority on the printers most likely being used by your customers. Currently (as of November 1992), this is the PostScript LaserWriter (driver version 7.1.2 or later), the StyleWriter (driver version 7.2.2), the Personal LaserWriter LS (driver version 7.2), and one or another of the most popular third-party printers. In addition, we recommend that you test both on an older LaserWriter (up to the LaserWriter IInt), and the newer ones (LaserWriter IIf, IIg, NTR), because of the differences in the PostScript interpreters and gray-level support.
  2193. Where to get documentation on writing a Macintosh printer driver
  2194. Date Written:  4/9/91
  2195. Last reviewed:  8/1/92
  2196. Where can I find documentation on how to write a Macintosh printer driver equivalent to the ImageWriter or LaserWriter driver? In particular, how are Printing Manager and QuickDraw commands translated into calls to the printer driver?
  2197. ___
  2198. DTS’s “Learning to Drive” document and “StdFileSaver” source code, available in AppleLink’s Developer Support folder and on the latest Developer CD Series disc, are helpful references.
  2199. Writing a Macintosh printer driver
  2200. Date Written:  5/3/89
  2201. Last reviewed:  8/1/92
  2202. I have a printer I would like to connect to the Macintosh. Where can I find information on writing a printer driver?
  2203. ___
  2204. A Macintosh printer driver is more than a standard device driver. A printer driver contains code to implement all of the standard Macintosh Printing Manager routines. The code includes routines like PrOpen/PrClose, and PrOpenDoc/PrCloseDoc. A Printing Resource File contains all of the resources (including code) to implement the Macintosh Printing Manager for a particular device. A driver works best with all Macintosh applications if it supports both the high- and low-level Printing Manager interfaces, as well as the PrGeneral (IM V:410) routine and its associated opcodes.
  2205. Apple is not currently supporting the development of Chooser-selectable device drivers, at least not those that support printers. There are many reasons for this, and here are at least a few of them:
  2206. First, there is no documentation or examples available. Each of the Apple printer drivers is unique. They are all written almost entirely in 68000 assembler, and consequently, are not very easy to read. Since each driver is different, the only real documentation for how the drivers work is the source code to the driver. There is some general interface information available, but important information, like how the driver manages its print record, is described only in the source code. This information could be extracted and distilled into some kind of document, but this brings up the next problem:
  2207. The Macintosh Printing Manager is currently being revised and enhanced. These revisions will require major changes to the architecture of the Printing Manager. It’s not clear what effect these changes will have on existing printer drivers, but it is very possible that the drivers that exist today will have to be revised significantly to run under the new Printing Manager.
  2208. Apple is designing and implementing the next generation Macintosh Printing Manager. Developers’ suggestions for features are being taken into account. One of the goals of the new architecture is to make writing drivers much simpler, and to allow the sharing of code between drivers. When this architecture becomes available, Apple will reconsider its position of driver development, and will probably end up with some kind of licensing agreement for developers that want to write drivers. Until then, the preceding reasons should be adequate justification for NOT attempting a Macintosh printer driver at this time.
  2209. If you still aren’t convinced, and want to write a driver despite the challenge, see the article in the December ’88 issue of MacTutor magazine. There is an example printer driver written in C. It is just a skeleton driver, and does not handle any of the more difficult problems such as line layout, font substitution, graphics, or banding. But it is a start, and gives you a general idea of the structure of a driver. Since some developers began writing their drivers before Apple discontinued support, DTS is still answering questions concerning driver development. However, these questions are limited to those that can be answered by the DTS engineers. You should also be aware that some of the techniques used by Apple printer drivers are considered proprietary. Information on methods used for line layout as well as certain aspects of font handling will not be disclosed.
  2210. X-Ref:
  2211. Printing Manager
  2212. Changing printer driver settings without using the dialog
  2213. Date Written:  11/6/91
  2214. Last reviewed:  6/14/93
  2215. To change default printer driver settings without using the dialog, keep a copy of the print record with the various settings you want, and when you want to choose your settings, just use your special print record. The current Macintosh print architecture doesn’t allow procedural access to the print record, so you must call the dialogs once for yourself, choose your settings, and then save a copy of the print record that is produced. Some settings are job-dependent, but values that are retrieved from the print record can be changed using this technique. You can only save the settings in the Style dialog. Call PrValidate when retrieving a print record from the resource fork to make sure it is “good.” 
  2216. See develop, issue #1, pages 58–65, for a complete discussion of changing default printer driver settings and sample code.
  2217. Macintosh print record wDev field
  2218. Date Written:  5/3/89
  2219. Last reviewed:  8/1/92
  2220. What is the Macintosh print record wDev value for the ImageWriter LQ, LaserWriter IISC, and AppleFax Modem?
  2221. ___
  2222. Apple strongly discourages the use of the wDev field in the print record for several reasons. First, this field contains a unique ID for each printer driver on the Macintosh. Coding your application to use this ID makes it device dependent, and device dependence will cause many problems in the future as the Macintosh Printing Manager continues to evolve. Many applications currently check for wDev = 3 to determine whether or not to send PostScript. Although the Apple LaserWriter driver has a wDev of 3, third-party printer drivers for PostScript devices do not, so if your application determines whether or not to send PostScript based on wDev alone, your application may incorrectly print with QuickDraw on third-party PostScript devices. A second problem concerns spoolers and spool files. If a spooler is installed between an application and the printer driver that is going to do the printing, the application receives the wDev ID of the spooler instead of the target driver. If the application makes assumptions based on this ID, it probably gets unexpected results. In the future, it may also be possible to redirect spool files. This means that a file that was originally spooled for a PostScript printer may be redirected to a QuickDraw device. If the spool file contains only the PostScript representation of the document, it will be useless to the QuickDraw device. Despite these strong warnings, some developers are convinced they need the wDev values, and there may be some vertical applications where they’re needed. For those cases, here is the current list of wDev IDs for Apple printer drivers:
  2223.     Device               wDev (Hi Byte)
  2224.     ImageWriter I/II:     1
  2225.     LaserWriter,
  2226.     LaserWriter Plus,
  2227.     LaserWriter IINT,
  2228.     LaserWriter IINTX:    3
  2229.     LaserWriter IISC:     4
  2230.     ImageWriter LQ:       5
  2231.     AppleFax Modem:      10
  2232. DTS does not support the use of these constants. They are definitely subject to change.
  2233. Determining if a printer driver accepts Color QuickDraw calls
  2234. Date Written:  11/21/90
  2235. Last reviewed:  8/1/92
  2236. How do you find out if a printer driver accepts Macintosh Color QuickDraw calls?
  2237. ___
  2238. Check to see if the printer driver has returned a color grafPort to your application after the call to PrOpenDoc (that is, the port that PrOpenDoc returns).
  2239. To determine if the grafPort is color, you need to check to see if rowBytes from the grafPort are less than 0. The following code fragment demonstrates this idea:
  2240. (* This function determines if the port passed to it is a color port. If *)
  2241. (* so, it returns TRUE. *)
  2242. FUNCTION ColorPort(portInQuestion: GrafPtr): BOOLEAN;
  2243. BEGIN
  2244.     IF portInQuestion^.portBits.rowBytes < 0 THEN
  2245.         ColorPort := TRUE
  2246.     ELSE
  2247.         ColorPort := FALSE;
  2248. END;
  2249. Printing in mixed Macintosh System 6/7 network
  2250. Date Written:  12/11/90
  2251. Last reviewed:  8/1/92
  2252. What is the recommended printer driver for a network environment with mixed operating systems (such as System 6.0.5 on a Macintosh Plus and 7.0 on two Macintosh IIfx systems)?
  2253. ___
  2254. In a mixed 6.0.x/7.0 network we recommend upgrading all systems to the 7.0 print drivers—even systems running 6.0.x. The 7.0 LaserWriter drivers work fine under system 6.0.x and will avoid any printer reinitialization problems. Use the 7.0 printing disk (or the printing install folder), and launch the Installer from that disk. It has scripts needed to install 7.0 print drivers on a 6.0.x system. Do not select the Installer options for printers from the main 7.0 Installer, because these scripts currently are only for systems running 7.0.
  2255. If a Personal LaserWriter NTR is used on the network, you must upgrade all workstations to the 7.1.1 LaserWriter driver or later. (The NTR requires at least LaserWriter 7.1.1.)
  2256. System 7.0 LaserWriter driver & choosing nonstandard page sizes
  2257. Date Written:  4/8/91
  2258. Last reviewed:  6/14/93
  2259. With the System 7.0 version of the LaserWriter driver, when the user selects Envelope from the Page Setup dialog, the page size returned by the driver is still a standard page: 8.5 x 11. How do you recommend that applications display the page size when the user has chosen a nonstandard page size?
  2260. ___
  2261. We recommend that you have the page preview show a full page instead of an envelope-sized page. The LaserWriter driver supports a large number of PostScript devices, and it can’t be sure whether the envelope will be fed on the right, left, or center of the paper tray. If you show the full page, a user can print on any device by putting the text in the correct location for that device.
  2262. Manufacturers of PostScript printers can add custom page sizes to the LaserWriter driver. If they do, the representation on the screen will be whatever they decide to define. Applications should not try to interpret custom page sizes. If your application ignores the results returned by the driver, you risk incompatibility down the road.
  2263. Asynchronous LaserWriter driver no longer supported
  2264. Date Written:  9/24/91
  2265. Last reviewed:  8/1/92
  2266. What is causing incorrect characters to be printed on the asynchronous LaserWriter driver we licensed from Apple for use with a non-Apple PostScript-equipped printer?
  2267. ___
  2268. The printing of incorrect characters is probably due to an incompatibility between the async driver and the version of PostScript being used in the printer.
  2269. The reason for the incompatibility is that the driver is no longer supported and hasn’t been revised for quite some time. The driver was originally developed outside of Apple, and Apple licensed the driver for its use. The company subsequently went out of business and the driver hasn’t been revved since.
  2270. PostScript and Apple’s AppleTalk LaserWriter drivers have been updated and changed quite a bit since then, which is why the characters print correctly when using AppleTalk, but not when printing asynchronously. The old async driver just doesn’t know how to handle the new PostScript versions and therefore prints “garbage” characters.
  2271. The SL Laser II driver is no longer supported by Apple, and at this time Apple has no plans to update this driver or write a new one. Since things work correctly with AppleTalk, you should confine usage to AppleTalk when printing PostScript to the LaserWriter. If this is unacceptable, you might check around with different clearinghouses to see if a third-party developer has a compatible, up-to-date asynchronous LaserWriter driver that you can use.
  2272. Use LaserWriter driver srcCopy instead of srcOr transfer mode
  2273. Date Written:  5/1/91
  2274. Last reviewed:  6/14/93
  2275. I’m creating PICTs that are comprised of many lines drawn in srcOr mode. When using the LaserWriter 6.x or 7.x driver with the Color/Grayscale radio button selected, some lines fail to print. Why is this happening?
  2276. ___
  2277. The problem is a bug in the LaserWriter driver. Sometimes, when using a CGrafPort, the driver doesn’t reproduce lines drawn in srcOr mode. (A CGrafPort is used when the Color/Grayscale print option is selected; in Black & White print mode, a regular grafPort is used.) A workaround is to use srcCopy instead of srcOr when drawing QuickDraw objects within your PICTs.
  2278. Save and restore long word if using $948 under System 7
  2279. Date Written:  6/11/91
  2280. Last reviewed:  8/1/92
  2281. Unless my Macintosh application restores the contents of the long word at $948 after using that space for globals, the Finder draws icons incorrectly and my third-party LaserWriter driver crashes. Is somebody now using $948 for other purposes?
  2282. ___
  2283. This is a known System 7 icon drawing bug, and also a bug with the printer driver that you are using.
  2284. The icon drawing utilities are trying to determine if a print page is currently open, by looking at that variable ($948 is part of printvars). This turns out not to be such a good idea, and it will be fixed in the next release of the system software.
  2285. The printer driver bug that you are experiencing is that every printer driver must return the variable at $948 to -1 when they are done printing. Also, while printing, the driver should set it to <> -1.
  2286. Update Backgrounder if using LaserWriter 7.0 under System 6
  2287. Date Written:  7/10/91
  2288. Last reviewed:  8/1/92
  2289. When we use the LaserWriter driver 7.0 with System 6.0, the Chooser’s Background Printing On button is always dimmed. Is there any way to enable background printing?
  2290. ___
  2291. To get the LaserWriter 7.0 driver to work with System 6.0.x, update your Backgrounder file with the version on the Printing Tools disk that’s used to install System 7.0.
  2292. In short, to use the 7.0 LaserWriter Driver, 7.0 PrintMonitor, and System 6.0.x, place these files from the System 7.0 Printing Tools installation disks into your System Folder. All three must be used together for printing to work correctly. After you’ve placed these files in the System Folder, you should find the Background Printing option enabled for your use.
  2293. There are no known incompatibilities with the 7.0 drivers and System 6.0.x, so everyone should use the latest drivers, even with a mixed environment. This will also get rid of “printer wars” that occur when users use more than one version of the LaserWriter driver to print to the same printer. (The printer must be reinitialized if the current user uses a different version of the driver than that used by the previous user.)
  2294. LaserPrep 7.0 file & AppleShare Print Server
  2295. Date Written:  7/15/91
  2296. Last reviewed:  8/1/92
  2297. The LaserPrep 7.0 file is included on the System 7 Printing disk and the System 7 Group Update CD for upgrading the AppleShare Print Server to support the LaserWriter 7.0 driver. The AppleShare Print Server has its own LaserWriter driver built in and all it needs to print is a LaserPrep file. In fact, the AppleShare Print Server completely ignores any LaserWriter driver installed in the System Folder of the server.
  2298. Page 49 of the System 7 Group Upgrade Guide states the following procedure for upgrading an AppleShare Print Server to support the System 7 LaserWriter drivers:
  2299. 1. Shut down the print server software.
  2300. 2. Install the printer driver update…
  2301. 3. Drag the LaserPrep icon from the Printer Update folder to the Server Folder of the print server Macintosh.
  2302. 4. Restart the print server Macintosh and the AppleShare Print Server software.
  2303. Actually, step #2 in the System 7 Group Upgrade Guide is unnecessary. Installing the printer driver update has no effect on the AppleShare Print Server software.
  2304. LaserWriter 7.0 driver and LaserPrep dictionary
  2305. Date Written:  8/29/91
  2306. Last reviewed:  6/14/93
  2307. In the old LaserWriter drivers it was possible to create a PostScript file with or without the LaserPrep dictionary (“f” or “k” key). Is it possible to generate a file without the dictionary with the LaserWriter 7.0 driver?
  2308. ___
  2309. In 7.0 printing, a LaserPrep dictionary is always sent with a print job. This is done to prevent constant reinitialization of the LaserWriter by conflicting printer drivers. You cannot prevent it from being sent. Fortunately the 7.0 version of the LaserPrep dictionary is much smaller (≈40K total) than its 6.x predecessors.
  2310. LaserWriter ignores ForeColor while filling smoothed polygon
  2311. Date Written:  10/8/91
  2312. Last reviewed:  8/1/92
  2313. When doing the FillRgn for drawing the fill of a smoothed polygon (as described in Macintosh Tech Note #91) the foreColor isn’t used on the LaserWriter. Any way to make it work?
  2314. ___
  2315. You’ve discovered a design limitation of the LaserWriter driver. Things that have patterns associated with them are rendered by using the LaserWriter screen operators. This results in an assumption of the foreground color being black and the background color being white, which is what’s causing the problem you noticed. In short, it makes the driver ignore your foreground and background colors.
  2316. You can work around the problem by working in an off-screen GWorld first and then CopyBitsing everything to the printer port using srcCopy. There are a couple of problems with this approach: First, don’t do it with text or your text will be turned into a bitmap and you’ll get the “jaggies.” Second, you’ll probably want to increase the printer port’s resolution from its default of 72 dpi for better results. A value of 288 dpi works nicely since it’s an even multiple of QuickDraw’s native 72-dpi resolution. Also, make sure that the GWorld you create has the same bounds as the printer port’s rPage rectangle to avoid unnecessary scaling and clipping. After you’ve done all that, draw into it and CopyBits the result to the printer port. The nice thing about doing everything off-screen first is that then you can use some of the non-printer-friendly transfer modes like blend or dithered. Also, you can use ForeColor/BackColor and get the right thing this way.
  2317. If you don’t want to use this method for all printers, (since it can be quite a memory hog), you can check for the LaserWriter driver and use this method in just that case. For other drivers, you should just print as normal.
  2318. So, what do you need to do all this? Well, to set the resolution of the printer port, use PrGeneral as described in Inside Macintosh Volume V and develop #3.
  2319. To determine whether you have the LaserWriter driver or not, check the high byte of the wDev field in your print handle. This is described in the Tech Note “Optimizing For The LaserWriter—Techniques.” While this method might break some day, it’s currently the best way to determine which driver you’re using, and Apple will have to let developers know before we break it.
  2320. If the high byte of the wDev is 3, then you either have the LaserWriter driver or a third-party driver impersonating the LaserWriter. Some PostScript drivers do that because many apps assume a wDev of 3 means a PostScript printer, and anything else doesn’t. By acting like Apple’s LaserWriter driver, they get preferential treatment from apps that “special case” for PostScript. That’s not really a problem in this situation.
  2321. LaserWriter driver PostScript error strings & document names
  2322. Date Written:  12/11/91
  2323. Last reviewed:  8/1/92
  2324. I discovered an interesting bug in the Macintosh LaserWriter driver. If the word “timeout” is in the name of a document, the LaserWriter driver will give a timeout error -8132. Are there similar magic words?
  2325. ___
  2326. PostScript error messages are sent from the LaserWriter to the driver as text streams. The driver must check these strings to see if they contain an error message. If a document is named something that contains the same string as a PostScript error message, the driver may think there’s an error when the printer sends the “status: printing document XXXXX” message. Other strings cause similar problems; one of them is “printer out of paper.” If you want to see the rest of the strings, take a look at the LaserWriter printer driver resource type 'PREC' ID = 109.
  2327. Personal LaserWriter NTR has longer product string
  2328. Date Written:  3/17/92
  2329. Last reviewed:  6/14/93
  2330. The following line of my PostScript code causes the Personal LaserWriter NTR to gag, but it has worked with all other Apple LaserWriter printers up to now:
  2331.   statusdict/product get str cvs show  % Gets & prints the name of the printer
  2332. where str is defined as:
  2333.   /str 20 string def
  2334. ___
  2335. The product name stored for this printer is (LaserWriter Personal NTR) or (Personal LaserWriter NTR), depending on whether you’re using statusdict or systemdict, respectively. In either case, the product’s length is 24 characters. Since you’re only allocating 20 characters for the 2nd string you use with cvs, you’re getting a rangecheck error. Changing str to:
  2336.   /str 24 string def
  2337. fixes the problem. You may want to make the string even larger than 24 characters to accommodate longer product names in the future.
  2338. Assumptions about the length of PostScript product strings are a common problem with new printers (having more verbose names). In fact, you should have the same trouble if you run your original PostScript on the Personal LaserWriter NT, which has a 23 character name.
  2339. LaserWriter II SC fonts and 4x bitmap size
  2340. Date Written:  11/17/89
  2341. Last reviewed:  6/14/93
  2342. Why do I need to have four times the bitmap size of the font I want to print in on the LaserWriter II SC?
  2343. ___
  2344. LaserWriter II SC fonts are four times the point size of the associated Macintosh screen font. The pixels on the screen are four times as far apart (center to center) as the dots printed by the LaserWriter SC. When the bitmaps for one of the printer fonts is printed, the result is a font with a resolution four times greater than that of the font displayed, but at a size identical to the font displayed on the screen.
  2345. Font families shipped with LaserWriters
  2346. Date Written:  11/17/89
  2347. Last reviewed:  8/1/92
  2348. What fonts and sizes are shipped with the LaserWriter Plus, LaserWriter IInt, LaserWriter IIntx, and LaserWriter SC?
  2349. ___
  2350. The LaserWriter Plus, LaserWriter IInt, and LaserWriter IIntx, shipped with a total of 11 font families with the sizes indicated below:
  2351. Times, Helvetica, Courier, Symbol: 9, 10, 12, 14, 18, 24
  2352. Palatino, Helvetica Narrow, ITC Bookman,
  2353. ITC Avant Garde Gothic, ITC Zapf Chancery,
  2354. ITC Zapf Dingbats, New Century Schoolbook 10, 12, 14, 18, 24
  2355. A total of four font families are shipped with the SC: Courier, Symbol, Times, and Helvetica in the following sizes: 9, 10, 12, 14, 18, 24, 36, 48, 56, 72,
  2356. 96.
  2357. Disable Graphics Smoothing for printing large bitmap images
  2358. Date Written:  5/3/89
  2359. Last reviewed:  6/14/93
  2360. When printing large (possibly scanned) Macintosh bitmap images, the page is printed with small lines running horizontally through the image. Why?
  2361. ___
  2362. In System 6.0 the QuickDraw DrawPicture call was revised to fix some problems. One of these problems concerned large bitmaps. To help solve the problem of bitmaps that were too large to be printed, DrawPicture was modified to “band” the CopyBits request if it was too large. Banding is the process of converting a large bitmap into several smaller bitmaps. This banding usually occurs vertically down the page. When DrawPicture bands a large bitmap into pieces, the smoothing algorithm of the LaserWriter is applied to each piece separately, instead of being applied to the entire bitmap at once. Since the process of smoothing involves removing some pixels, hairlines will be created between the bitmap bands. There is no way to tell the LaserWriter driver that the smaller bitmaps are all part of one large bitmap, so the only solution to this problem is to disable Graphics Smoothing when printing large bitmap images.
  2363. Difference between LaserWriter 7.0 and 7.1 Namer
  2364. Date Written:  3/3/92
  2365. Last reviewed:  8/1/92
  2366. Apple Software Licensing’s “Exhibit C” lists localized Namer 7.0 versions in several languages, and mentions that these localized versions of the Namer are available in version 7.1. What is the difference in the Namer between 7.0 and 7.1?
  2367. ___
  2368. The main difference between the LaserWriter utility 7.0 and 7.1 is that part of the Namer has been integrated into the 7.1 version of the software. Until the LaserWriter utility 7.1 was made available, the Namer was a stand-alone application. However, the LaserWriter utility does not do everything the Namer does. For example, the Namer renames AppleTalked ImageWriters, but the LaserWriter utility doesn’t. For all your printer configuration needs, you should use the 7.1 version of the software.
  2369. ImageWriter and printing multiple copies in draft mode
  2370. Date Written:  1/6/92
  2371. Last reviewed:  6/14/93
  2372. Our application can’t print multiple copies on the ImageWriter in Draft mode. If we type in 3 copies in the ImageWriter driver dialog box in Draft mode, we only get one copy. Everything prints fine in Best or Faster modes. Is this a bug in the ImageWriter driver?
  2373. ___
  2374. Although it seems like this must be a bug in the ImageWriter driver, it’s not. In Draft mode, the application that’s printing must make sure the required number of pages are printed. This involves cycling through the app’s print loop for each copy to be printed.
  2375. In Draft mode on an ImageWriter, nothing is spooled to disk; the data is immediately sent to the printer. Therefore, the data is no longer available once it’s sent to the printer (and there’s no way for the print driver to resend it for multiple copies). When the ImageWriter spool-prints, the file that’s created is printed the required number of times for you. Therefore, your app only needs to handle multiple copies when printing in Draft mode.
  2376. Here’s what your app should do:
  2377. 1. Validate the print record and present the job dialog. This allows the user to choose how many copies to print and allows the printer driver to adjust the print record to reflect how many copies your program has to print.
  2378. 2. Get the number of copies that you’re expected to handle from the print record. In the case of spool printing, this number will be set to 1 (since the multiple copies are handled for you by the printer driver). In any case, the following Pascal code will give you the correct info.
  2379.     numCopies:= printHdl^^.prJob.iCopies;  (* From IM 2, pg. 151. *)
  2380. 3. For each copy in numCopies, loop through the PrOpenDoc/PrCloseDoc section of your code.
  2381. This method is demonstrated in the code for the Macintosh Tech Note “A Printing Loop that Cares…,” which describes a model print loop.
  2382. Dogcow logo is trademarked
  2383. Date Written:  9/10/92
  2384. Last reviewed:  6/14/93
  2385. We would like to use the “dogcow” icon in our Page Setup dialog. Is the dogcow trademarked, and are there any restrictions on using this icon in our software?
  2386. ___
  2387. Yes, the dogcow logo (along with its call, “Moof!”) is a trademark of Apple and is proprietary. The dogcow appears on Apple’s Developer CD Series disc and in other material. Apple has a pending U.S. registration on it. Accordingly, it’s not available to third-party developers as an icon or file symbol.
  2388. “Printer driver is MultiFinder compatible” bit
  2389. Date Written:  7/29/92
  2390. Last reviewed:  6/14/93
  2391. Could you tell me what the “printer driver is MultiFinder compatible” bit is used for?
  2392. ___
  2393. The “printer driver is MultiFinder compatible” bit provides two features. First, it allows the printer driver resource file to be opened by multiple clients. This was obviously needed to support multiple applications printing simultaneously under MultiFinder. The other feature provided by the flag is the loading of PDEFs into the system heap rather than the application heap (which is where they go under the Finder).
  2394. The MultiFinder-compatible bit has a major limitation: If your driver has this flag set, you aren’t allowed to add or resize resources, or do anything else that would cause the RAM-resident resource map to change. Although MultiFinder lets multiple applications open the printer resource file at the same time, it has no control over the resource map that gets loaded by the Resource Manager when the file is opened. Because of this, each client gets its own personal copy of the resource map. When these clients get done with the file, they write the resource map back to the file (via UpdateResFile). Obviously, if the resources have changed in any way, the last client to call UpdateResFile is the only one whose changes will be recorded. This is a “thrill seeker” method of handling the printer driver resource files, but since none of the Apple printer drivers currently add or resize resources, it made sense.
  2395. So the bottom line here is that if you want your drivers to be compatible under MultiFinder, you’ll have to implement a scheme that doesn’t require adding or resizing resources. It’s OK to change the data in a resource, as long as you don’t change its size. Changing the data won’t cause changes to the resource map, so each client will still have accurate copies of the map.
  2396. Here’s what would happen to your printer driver’s resources under the Finder and MultiFinder when the MultiFinder-compatible bit is set:
  2397. • Under the Finder in system software version 6.0.x: All resources are loaded into the application heap—regardless of the resource attribute’s bit setting. If the resource has the “load into the system heap” bit set, it will still be loaded into the application heap under the Finder. This makes sense in the Finder world because the application heap will usually have more room than the system heap.
  2398. • Under MultiFinder in System 6 or System 7: All the printer driver’s resources will be loaded into the system heap. This is true whether the “load into the system heap” bit is set or not.
  2399. Why does the resource loading occur this way, even when the resource’s “load into the system heap” bit is set? Patches to the GetResource trap load all your printer driver’s resources into the system heap when the MultiFinder-compatible bit is set under MultiFinder, and into the application heap under the Finder (as described above), which is why you can’t override this behavior.
  2400. By the way, you should be aware of the SetPDiMC MPW tool, which is available on the Developer CD Series disc. It will automatically set the MultiFinder-compatible bit for you when you build your printer driver.
  2401. Use FillCRect off-screen, not directly to printer port
  2402. Date Written:  8/25/92
  2403. Last reviewed:  11/30/92
  2404. We’re having problems with color patterns using the LaserWriter driver version 7.1.2. If we create a 'ppat' resource in ResEdit (32 x 32 bits, in this case) and then do a FillCRect to the port returned by PrOpenDoc (with color set so that it’s a cGrafPort) with the pattern loaded by GetPixPat, we get a weird pattern. Doing the same to an off-screen GWorld and using CopyBits to copy to the printer port works fine, if a little slowly. Are we missing something here?
  2405. ___
  2406. You need to use the FillCRect call off-screen rather than directly into the printer port, for at least two reasons. First, the LaserWriter driver doesn’t support filling objects with anything but black-and-white patterns because it uses the PostScript halftone screen functions to draw patterns. Second, the LaserWriter driver doesn’t understand (or handle) pixPats. Therefore, your only recourse is the one you discovered—to copy to and from GWorlds. Unfortunately, FillCRect doesn’t work with the LaserWriter drivers through version 7.2. After version 7.2 this probably won’t be a problem.
  2407. Color/Grayscale button on a non–Color QuickDraw Macintosh
  2408. Date Written:  8/31/92
  2409. Last reviewed:  6/14/93
  2410. The LaserWriter driver displays the Color/Grayscale option even on a non–Color QuickDraw Macintosh, which seems odd because the option normally causes the driver to return a CGrafPort to the calling application, and CGrafPorts are only available under Color QuickDraw. What happens if you’re printing original QuickDraw colors using the LaserWriter driver on a non–Color QuickDraw system? Does the driver just use the Black & White code regardless of whether the Color/Grayscale button is selected?
  2411. ___
  2412. Regardless of whether Color/Grayscale is selected or not, the driver returns a grafPort because it’s not running on a Color QuickDraw machine. But, if the Color/Grayscale option is chosen on a Macintosh without Color QuickDraw, the driver doesn’t just use the Black & White code to print. Instead, it sends the colors to the printer as best it can without Color QuickDraw. This can result in three different sets of output when printing classic QuickDraw colors:
  2413. • Black & White button selected (identical output whether the system has Color QuickDraw or not)
  2414. • Color/Grayscale button selected on Color QuickDraw Macintosh
  2415. • Color/Grayscale button selected on non-Color QuickDraw Macintosh
  2416. PR 515 - Printing Manager Q&As
  2417. Printing    
  2418. Revised by:    Developer Support Center    September 1993
  2419. Written by:    Developer Support Center    October 1990
  2420. This Technical Note contains a collection of Q&As relating to a specific topic—questions you’ve sent the Developer Support Center (DSC) along with answers from the DSC engineers. While DSC engineers have checked the Q&A content for accuracy, the Q&A Technical Notes don’t have the editing and organization of other Technical Notes. The Q&A function is to get new technical information and updates to you quickly, saving the polish for when the information migrates into reference manuals.
  2421. Q&As are now included with Technical Notes to make access to technical updates easier for you. If you have comments or suggestions about Q&A content or distribution, please let us know by sending an AppleLink to DEVFEEDBACK. Apple Partners may send technical questions about Q&A content to DEVSUPPORT for resolution.
  2422. New Q&As in this Technical Note:
  2423. OK to call WaitNextEvent if modal window is frontmost
  2424. OK to call WaitNextEvent if modal window is frontmost
  2425. Date Written:  1/20/93
  2426. Last reviewed:  6/14/93
  2427. I’ve read in “Print Hints: Top 10 Printing Crimes” that a program shouldn’t call WaitNextEvent while the Print Manager is open, but I call WaitNextEvent in my pIdleProc so my application can detect a user cancellation. Could this cause a problem?
  2428. ___
  2429. The reason you shouldn’t call WaitNextEvent is to prevent the system from switching to another application. If you have a modal dialog-type window in front (the one with the modal window proc ID), the system will never switch applications and it’s safe to call WaitNextEvent. This is why all Apple’s drivers that call WaitNextEvent put up a modal dialog box. If you have a modal status window frontmost when your pIdle procedure is called, you’re in no danger.
  2430. Macintosh Printing Manager error -8132
  2431. Date Written:  1/1/90
  2432. Last reviewed:  6/14/93
  2433. What is Macintosh Printing Manager error -8132?
  2434. ___
  2435. Error -8132 is generated when the selected printer times out. AppleTalk printers monitor the time between data packets that are sent to them. These devices will wait a maximum of two minutes without data until generating a time-out error. Applications such as database report generators sometimes require longer than two minutes to sort or format their data. These applications may receive the -8132 error. One workaround for this problem is to spool the report to a file that can be printed when sorting/formatting is completed.
  2436. Another possible solution is to change the amount of time the LaserWriter waits for data until it times out. Keep in mind that the time-out in the LaserWriter exists for a reason. Say a user starts printing a large document and leaves for the day. About halfway through the document, the user’s Macintosh crashes, leaving the printer waiting without data. In two minutes, the LaserWriter times out, and is once again available for other users on the net. However if the time-out is disabled by the first user’s job, the printer is useless until rebooted. To avoid disabling the time-out, increase the time-out value so that the device times-out if the job takes too long to print, but does not time-out for normal delays. This is done by sending the following Postscript to the LaserWriter with a Postscript downloading utility:
  2437.  serverdict begin 0 exitserver
  2438.  statusdict begin 0 0 0 setdefaulttimeouts
  2439. See the Apple’s LaserWriter Reference for more information.
  2440. The only other way to handle this problem is to periodically send some data to the printer. Do this about once a minute or so to prevent the printer from timing out. Use the PostScriptHandle PicComment to send this “tickle” data so that it is only sent to PostScript printers that have the ability to time-out. (Quickdraw printers won’t see the data.) Another reason for using the PostScriptHandle PicComment involves the internal buffering of the LaserWriter driver. The LaserWriter driver maintains a 4K internal buffer for the PostScript that it sends. If you send just a few characters as your tickle data, they are buffered in the driver, and the device still times-out. The only way to ensure that your tickle data makes it to the device is to send a 4K block via the PostScriptHandle PicComment. Needless to say, sending 4K blocks over AppleTalk once a minute is going to cause some network traffic, but it’s still another possible workaround.
  2441. Macintosh Printing Manager error -8133
  2442. Date Written:  1/1/90
  2443. Last reviewed:  8/1/92
  2444. What is Macintosh Printing Manager error -8133?
  2445. ___
  2446. Printing Manager error -8133 occurs when the PostScript interpreter of the LaserWriter (or any other PostScript printer) generates a PostScript error. A description of the PostScript command that caused the error is displayed in the status window. This error often occurs when an application sends PostScript directly to the printer, and that PostScript contains an error. To debug this problem, look at the PostScript generated by the driver. Hold down the Command-F key right after clicking okay in the Print dialog. A file named PostScript0 will be created in the current directory. With the 7.x LaserWriter drivers, just select the PostScript File radio button in the Print dialog.
  2447. Identifying Macintosh’s currently selected printer
  2448. Date Written:  1/1/90
  2449. Last reviewed:  8/1/92
  2450. How can I find out which printer the user has selected with the Macintosh Chooser? How can I change it without going through the Chooser?
  2451. ___
  2452. The type of the currently selected printer is stored in the System file in 'STR ' resource ID -8192. This will be the name of the driver selected, such as LaserWriter or ImageWriter. The name of the actual printer selected will be in the driver file (same name as the printer type chosen) in 'PAPA' resource ID -8192. Look at this resource with ResEdit to see what is in it.
  2453. You can change the 'STR ' and 'PAPA' resources, but it may not work now or in the future. DTS does not recommend changing the system file or circumventing the Chooser! The Chooser is a very complicated piece of software, and it has many dependencies. Implementing the chooser within your application would make your application dependent on a particular version of the system software. Like the Chooser, your application would then have to be revised each time a new system is released.
  2454. How to save Macintosh Page Setup and Print dialog options
  2455. Date Written:  5/3/89
  2456. Last reviewed:  6/14/93
  2457. How do I save options set in the Macintosh Page Setup and Print dialogs?
  2458. ___
  2459. The only supported method to save the dialog options is to save the Print Record that was passed to the PrStlDialog/PrJobDialog calls. This print record contains the options chosen in the Page Setup and Print dialogs. Although these options are saved in the print record, they cannot be used as defaults for the Print dialog. For example, say the user chooses landscape printing in the Page Setup dialog, and sets the number of copies to 5 in the Print dialog. If the print record is passed to PrStlDialog, the dialog shows that landscape printing was selected in the print record. However, if that print record is passed to PrJobDialog, number of copies is shown as 1, because options in the PrJobDialog are considered to be “job dependent,” as opposed to “document dependent.”
  2460. The best method for saving the print record is to save it as a resource in your document’s resource fork. Since the print record is already pointed to by a valid handle, creating a resource is easy. Here are the required steps:
  2461. 1. Save the refNum returned by CurResFile;
  2462. 2. Make sure the resource fork of the document file is opened using OpenResFile (IM I:115).
  2463. 3. Now that you have a place to put the resource, you must get the resource manager to create it for you. First, pick a type and ID for your resource. You can use the Unique ID function (IM I:121) to generate the ID. Next, call the AddResource procedure (IM I:124). This procedure takes four parameters:
  2464.  Parameter  Type     What to Pass
  2465.  --------------------------
  2466.  theData    Handle   The handle to the currently valid print record.
  2467.  theType    ResType  The four character resource type you have chosen.
  2468.  theID      INTEGER  The ID returned from the UniqueID function.
  2469.  name       Str255   The name for this resource or '' if none.
  2470. 4. Call WriteResource (IM I:125), and UpdateResFile (IM I:125) to make sure the new resource gets saved into the file.
  2471. 5. Reset the currently selected file back to whatever it was before you began the save using UseResFile (IM I:117).
  2472. The important things to keep in mind when doing this are:
  2473. 1. Make your resource type something different than those used by the Print Manager. This prevents the Print Manager from getting confused and grabbing the wrong resource. Types to avoid include 'PREC', 'PDEF', and 'POST'.
  2474. 2. Don’t make any assumptions about the size of the print record. If you really need to know the size, use GetHandleSize.so that if the record gets bigger in the future, your code will still work.
  2475. 3. Be sure to pass the record that you get from your document to PrValidate before using it. This ensures that the record gets updated if any changes have been made to record structure or contents since the record was saved.
  2476. MacApp and SetRsl print driver resolution
  2477. Date Written:  4/16/92
  2478. Last reviewed:  6/14/93
  2479. We’ve been trying to use the standardPrint handler from MacApp 2 to print some views. The problem is that we would like the printout to come out at 300 dpi on the LaserWriter, and the print handler’s device resolution fields (which come from the device driver) tell it to draw at 72 dpi. How, can I get a PenSize(1,1); MoveTo(100,100); LineTo(300,300); draw at 300 dpi and make a nice fine line? Please refer me to the needed documentation.
  2480. ___
  2481. The mechanism by which your application can find out the chosen printer’s real resolution, and then draw with it, is documented “Meet PrGeneral, the Trap That Makes the Most of the Printing Manager,” in issue #3 of develop magazine (July 1990). You can find it, along with its accompanying code and application, on the Developer CD, E.T.O., and AppleLink.
  2482. The DTS Sample Code SC.009.FracApp300 on the Developer CD shows how to use PrGeneral in an application built with MacApp 2.
  2483. Printing patterns at higher resolutions with GetRslData & SetRsl
  2484. Date Written:  11/7/90
  2485. Last reviewed:  6/14/93
  2486. Is there a way that I can make my Macintosh fill patterns print at a higher resolution (more than 72 dpi), but have my patterns still print as patterns?
  2487. ___
  2488. To make your patterns print at the printer’s resolution, you need to use Printing Manager PrGeneral’s GetRslData and SetRsl opcodes to get and set the resolution, and you must scale the pattern to match. Let me explain.
  2489. If we do not scale our patterns up to the printer’s resolution before print time, we would get “big chunky” patterns because the printer driver would need to scale the patterns on the fly from 72 dpi to its resolution. Therefore, we use the “cookie cutter” approach to “place” the pattern into the object that is being filled. The size of the cookie cutter (that is, the destination Rect) depends on the “scaleFactor”. For example, a scaleFactor of 2 will have a destination rect of 16 x 16. We will then CopyBits the pattern one square at a time into the object that is being filled.
  2490. XRefs:
  2491. Inside Macintosh Volume V, pages 410-416
  2492. “Meet PrGeneral,” develop, July 1990
  2493. Call Printing Mgr’s bottleneck to send StdText to printer driver
  2494. Date Written:  11/7/90
  2495. Last reviewed:  6/14/93
  2496. We need to use the Macintosh toolbox call StdText instead of DrawChar, DrawString, and DrawText to accomplish horizontal scaling and fractional point sizes, but StdText does not work on the LaserWriter IISC. Is there any workaround?
  2497. ___
  2498. The problem is that you are calling the low-level bottleneck directly, and the Printing Manager has replaced the bottleneck completely with its own. So when you are actually printing, the print driver will not see your call to StdText. The work-around for this is to call the Print Manager’s bottleneck itself when you are printing. You can do this in the following way:
  2499. /* typedef the function */
  2500. typedef pascal void (*StdTextProcPtr)( short, Ptr, Point, Point );
  2501. void tstDrawStuff( pInfo, thePort, pageNum )
  2502. TPrint pInfo;
  2503. GrafPtr thePort;
  2504. unsigned short pageNum;
  2505. {
  2506.    StdTextProcPtr Proc;     /* declare a variable here */
  2507. /* do your clipping etc. */
  2508. /* TEST -- no good w/o PriMon */
  2509. /* do your moveto etc. */
  2510. /* Is there a replacement bottleneck ?*/
  2511. if ( thePort->grafProcs )  {
  2512.     Proc = (StdTextProcPtr)thePort->grafProcs->textProc; /* yes, so grab it */
  2513.     (*Proc)( strlen("HELLO") , (Ptr) "HELLO", numer, denom );
  2514. }
  2515. /* else just call standard text */
  2516. }
  2517. This technique will work in both background and foreground printing. I have tested this solution on the Personal LaserWriter SC and the LaserWriter IINTX, and it prints fine.
  2518. Modifying PDEFs to have printer driver jump into dialog code
  2519. Date Written:  11/9/90
  2520. Last reviewed:  6/14/93
  2521. Could you please point me to the correct section in “Learning to Drive” (or send me an example) that we would need to modify the appropriate PDEF resource in order to have the driver jump to our dialog code?
  2522. ___
  2523. Pages 15-18 discuss the contents of the various PDEFs. You will need patch the appropriate PDEF to get your required functionality. You should also realize that patching PDEFs is not an easy task, nor will it always survive “new” Macintosh LaserWriter driver releases. I want you to know that before you go too far down the PDEF patching road.
  2524. By the way, we do know of a couple of developers that have patched PDEFs successfully. The following paragraphs are a “high-level” look at patching a PDEF:
  2525. To patch a PDEF, you must write an installer application that lets users choose the printer driver they want to modify via Standard File. You can cause Standard File to display only printer drivers by telling it to display only files of type “PRER”. Once the user has selected a driver you need to scan the driver for the PDEF 0 and 1 resources. When you find one of these you read it in and modify it.
  2526. However, I'll give you a quick overview of what you need to do. PDEF 0 & 1 both start with jump tables (a table of JMP instructions followed by the PC relative address to jump to). The JMP to PrClosePage always begins at offset 12. So what your installer needs to do after it loads the resource is grab the eighth word in the resource. That is the offset to the actual start of the PrClosePage code. Then you have to resize the handle so that it is big enough to hold your patch and then BlockMove {IM II-44} your code into the end of the handle. The following illustration might help:
  2527.          JMP $0486              << Note: some PDEF's have multiple JMPs at
  2528. * - - - - - - - - - - - - - *            the beginning of the code. The
  2529. *                           *            original offset to PrClosePage was
  2530. * >> Original PDEF code  << *            $0386.
  2531. *                           *
  2532. $0386 --> PrClosePage           << Note: most PDEF's have multiple printing
  2533. *                           *            calls defined.
  2534. *                           *
  2535. * - - - - - - - - - - - - - *
  2536. $0486 --> {{{  Your Code  }}}
  2537. *                           *   << You resize the resource handle to this
  2538. *                           *            and blockmove your code in here.
  2539. *                           *
  2540. * - - - - - - - - - - - - - *
  2541.          JMP $0386              << At this point we jump into the printer
  2542.                                       driver's original code for PrClosePage.
  2543. Note: The previous illustration is not to scale nor completely accurate in regards to the addresses used. Please consult “Learning To drive” for the correct offsets for each PDEF.
  2544. Then replace the original offset to PrClosePage with the offset to your new code. Remember that this is PC relative so you would calculate it like this: If the original PrClosePage JMP was JMP 10(SP) and the size of the original PDEF was 50 bytes, then you need to replace the JMP 10(SP) with JMP 50-16(SP). In other words, you need to JMP to what was formerly the end of the PDEF resource but what is now the beginning of your code (subtract 16 because the offset table is 16 bytes long. Refer to “Learning to Drive” for more details). Then on the end of your code, add a JMP ((SizeOfJumpTable + originalOffset) – (sizeofOriginalPDEF + SizeOfYourCode))(SP). Your code will end with a JMP to a negative offset off the PC back to the original PrCloseRoutine.
  2545. If you are willing to support only system software later than version 3.3 (basically that means that you won’t be supporting Macintosh 512K and 512KE computers), you don’t have to deal with all the PDEF changing, and you can simply patch out the $A8FD trap and look for the proper selector on the stack. (Use SysEnvirons to be sure that you are on a system later than version 3.3) This will work because the newer libraries (that is, any library that shipped since the Macintosh II shipped) first checks for the trap and jumps there if the trap exists so even if the application has linked in the printing library they still end up calling the trap on systems after 3.3.
  2546. Determining if printer supports color and/or grayscale printing
  2547. Date Written:  3/14/91
  2548. Last reviewed:  8/1/92
  2549. Is there any way to determine whether I’m printing to either a color printer or a printer simulating color, such as the LaserWriter set for Color/Grayscale?
  2550. ___
  2551. Check the grafPort returned by your call to PrOpenDoc. If the rowBytes of the grafPort is less than 0, the Printing Manager has returned a color grafPort. You can then make Color QuickDraw calls into this grafPort. LaserWriter driver version 6.0 and later returns a color grafPort from the PrOpenDoc call, if the Color/Grayscale button has been set.
  2552. The following code fragment demonstrates this:
  2553. (* This function determines whether the port passed to it is a *)
  2554. (* color port. If so, it returns TRUE.                         *)
  2555. FUNCTION IsColorPort(portInQuestion: GrafPtr): BOOLEAN;
  2556. BEGIN
  2557.   IF portInQuestion^.portBits.rowBytes < 0 THEN
  2558.     IsColorPort := TRUE
  2559.   ELSE
  2560.     IsColorPort := FALSE;
  2561. END;
  2562. A third-party printer driver should return the type of grafPort that represents the abilities of its printer. Therefore, if the printer supports color and/or grayscale, and if Color QuickDraw is present, the application will receive a color grafPort after calling PrOpenDoc. Otherwise, if the Macintosh you’re running on does not support Color QuickDraw, you should return a black-and-white grafPort.
  2563. Using LaserWriter fonts with StyleWriter
  2564. Date Written:  3/22/91
  2565. Last reviewed:  6/14/93
  2566. Can StyleWriter use all the Adobe fonts for my LaserWriter? Can StyleWriter print the encapsulated PostScript drawings I’ve developed? Does TrueType software come with the StyleWriter?
  2567. ___
  2568. The difference between the StyleWriter and a regular LaserWriter (other than one’s got a laser and the other doesn’t) is that the LaserWriter has PostScript built-in; the StyleWriter does not. The StyleWriter, in fact, has nothing built-in, and only recognizes basic “put this dot here” types of commands. Even sending it pure ASCII accomplishes nothing.
  2569. TrueType software is shipped with the StyleWriter, because it can image fonts at any resolution with excellent quality, much like PostScript. The TrueType software is intended for users of system versions 6.0.7 and later, but prior to System 7. System 7 includes support for TrueType.
  2570. You can use PostScript images and fonts with the StyleWriter, but just as with the ImageWriter, you’ll have to have something that images them in memory before sending them to the printer (in other words, a Macintosh-resident PostScript interpreter).
  2571. Personal LaserWriter LS 1.1 driver is faster
  2572. Date Written:  8/9/91
  2573. Last reviewed:  6/14/93
  2574. My LaserWriter LS is very slow when printing from my Macintosh SE. Any suggestions?
  2575. ___
  2576. Use the new LaserWriter LS driver version 1.1 or later. It was released after System 7.0, and is available on AppleLink or from your dealer.
  2577. If you’re printing Word files, Microsoft’s TrueType INIT will help. It’s available from MicroSoft Technical Support or from commercial bulletin board services.
  2578. ImageWriter II 6.1 & 7.0 driver PrGeneral/PrStlDialog bug
  2579. Date Written:  9/11/91
  2580. Last reviewed:  6/14/93
  2581. If an application uses PrGeneral to set draftBits mode on an ImageWriter II (using the 6.1 or 7.0 drivers) and then does a PrStlDialog, a fatal crash occurs. This happens with both the AppleTalk and non-AppleTalk drivers. This only happens on Macintosh systems with Color QuickDraw.
  2582. The problem is connected to the two 'dctb' resources which were added in the 6.1 driver. When the landscape icon is being grayed out (since it’s unsupported in draftBits mode), the driver is jamming the gray pen pattern directly into the GrafPort. While this brute-force method works fine with GrafPorts, the 'dctb' resources make the Dialog Manager use a CGrafPort now. Jamming the pattern into this CGrafPort as if it were a GrafPort makes a mess and causes a fatal crash, manifesting itself as a “division by zero” error, for example.
  2583. To work around the problem, check to see if you are printing to a 6.1 or 7.0 ImageWriter driver, and if so, do the style dialog before setting draftBits. The disadvantage of this is that setting draftBits before calling PrStlDialog causes the 50% reduction and landscape controls to be disabled, and this method doesn’t. Therefore, after the style dialog, you should check to see if the user selected landscape printing or 50% reduction by calling PrGeneral (getRotnOp) and checking bit 3 of the wDev field (See “Learning To Drive” on the Developer CDs for more about the wDev.) If the user selected either of those options, display a dialog warning them that those features will be ignored. Then, call PrGeneral to set draftBits and continue normally. PrGeneral will adjust the print record so that options not supported with draftBits are turned off. If a non 6.1/7.0 ImageWriter driver is used, the code should set draftBits as usual, before the PrStlDialog call.
  2584. This workaround is the better alternative to hacking the 'dctb's out of the driver or patching around the problem, although it doesn’t help 7.0 users running applications that already make use of the draftBits option. The following Pascal snippet demonstrates how to use the workaround:
  2585. (* Sample snippet that demonstrates how to work-around the
  2586.    'dctb' bug in the ImageWriter II 6.1 and 7.0 drivers.
  2587.    Bug causes a crash when doing a style dialog
  2588.    after setting draftbits with PrGeneral.
  2589.  *)
  2590. {
  2591.   What's what in the code snippet that follows.
  2592.   
  2593.   thePrRecHdl        : THPrint;
  2594.   rslData            : TSetRslBlk;
  2595.   draftData          : TDftBitsBlk;
  2596.   rotnData           : TGetRotnBlk;
  2597.   isBadImageWriter   : Boolean;
  2598.   isLandscape        : Boolean;
  2599.   isReduced          : Boolean;
  2600. }
  2601.       PrOpen;
  2602.     IF (PrError = noErr) THEN
  2603.     BEGIN
  2604.       PrintDefault(thePrRecHdl);
  2605.       IF (PrError = noErr) THEN
  2606.       BEGIN
  2607. {See if we're using a version 6.1 or 7.0 ImageWriter driver.}
  2608.         IF (thePrRecHdl^^.prStl.wDev DIV 256) = 1 THEN
  2609.           isBadImageWriter := (PrDrvrVers = 61) OR (PrDrvrVers = 70)
  2610.         ELSE
  2611.           isBadImageWriter := FALSE;
  2612.           
  2613.         IF NOT (isBadImageWriter) THEN
  2614.         BEGIN
  2615. {Set draftBits mode now, if not our special case.}
  2616.           draftData.iOpCode := draftBitsOp;
  2617.           draftData.hPrint := thePrRecHdl;
  2618.           PrGeneral(@draftData);
  2619.         END;
  2620. {Do the style dialog.}
  2621.         IF (PrStlDialog(thePrRecHdl)) THEN
  2622.           IF (isBadImageWriter) THEN
  2623.           BEGIN
  2624. {If so, see if they selected rotation or 50% reduction.}
  2625.           
  2626.             rotnData.iOpCode := getRotnOp;
  2627.             rotnData.hPrint := thePrRecHdl;
  2628.             PrGeneral(@rotnData);
  2629.             isLandscape := rotnData.fLandscape;
  2630.             isReduced := BTst(thePrRecHdl^^.prStl.wDev, 3);
  2631. {If so, warn them that those things will be ignored.
  2632.  Preferably use something other than DebugStr…      }
  2633.           
  2634.             IF (isLandscape) OR (isReduced) THEN
  2635.               DebugStr('Bad ImageWriter; landscape and/or reduced.');
  2636. {Now, set draftBits mode, since we didn't before.}
  2637.             draftData.iOpCode := draftBitsOp;
  2638.             draftData.hPrint := thePrRecHdl;
  2639.             PrGeneral(@draftData);
  2640.           END;
  2641.           IF (PrJobDialog(thePrRecHdl)) THEN 
  2642.           BEGIN
  2643.             {Print}
  2644.           END;
  2645.       END;
  2646.     END;
  2647.     PrClose;
  2648. How to abort printing while PrPicFile is executing
  2649. Date Written:  9/27/91
  2650. Last reviewed:  6/14/93
  2651. Can I abort printing from within PrPicFile? My attempts haven’t been succesful.
  2652. ___
  2653. The following Pascal procedure is roughly the same as the default idle procedure—the one the system supplies for you when you don’t supply one of your own:
  2654. procedure MyPIdleProcedure;
  2655.   var
  2656.     pIdleEventRecord: EventRecord;
  2657.   begin
  2658.     if GetNextEvent(keyDownMask, pIdleEventRecord) then
  2659.       begin
  2660.         if ((BitAnd(pIdleEventRecord.message, charCodeMask) = 
  2661.           longint('.')) and
  2662.         (BitAnd(longint(pIdleEventRecord.modifiers), cmdKey) = 
  2663.           cmdKey)) then
  2664.             PrSetError(iPrAbort);
  2665.       end;
  2666.   end;
  2667. (This is written in Think Pascal, but it should work fine under MPW Pascal if you change the “BitAnd” functions to “BAND”.)
  2668. As you can see, the system aborts when you press Command-period by using PrSetError to the constant iPrAbort, which is the same error returned when the user clicks “Cancel” in the style or job dialogs. If you set the error to iPrAbort, the system will take care of the rest. Your print loop will also gracefully cancel, provided you follow the guidelines in the Macintosh Technical Note “A Printing Loop That Cares.”
  2669. Disabling ImageWriter’s initial formfeed
  2670. Date Written:  1/23/92
  2671. Last reviewed:  6/14/93
  2672. When our product-to-be prints to the ImageWriter II there is an automatic (and undesirable in our product) sheet feed before actual printing begins. To make matters worse, it always feeds 11", even though our form is a different length. Is there a way to avoid this?
  2673. ___
  2674. The ImageWriter ejects a page before printing with the “No Gaps” option selected because it assumes that the page is aligned with a small gap between the perforation and the print head. So the printer ejects the page and re-aligns the print head at the perforation of the next page.
  2675. The sample code below illustrates how to prevent that nasty form feed from occurring. The program temporarily disables the “No Gaps” option if it is selected until after PrOpenDoc is called, preventing a formfeed from occurring. After PrOpenDoc is called, the program re-enables the “No Gaps” option.
  2676. Please note that this sample only works with the ImageWriter II and the ImageWriter LQ printers—probably the only series that supports the “No Gaps” option. The sample shows how to check for these types of printers, so you shouldn’t have any problems.
  2677. PROGRAM NoGapsWA;
  2678. {$U-}
  2679. USES PasInOut,Memtypes,QuickDraw,OSIntf,ToolIntf,PackIntf,MacPrint;
  2680. CONST
  2681.   bDevLaser = 3;
  2682.   bDevImageWriter     =   1;
  2683.   bDevImageWriterLQ   =   5;
  2684. PROCEDURE DrawStuff(theWorld : Rect);
  2685.   { Draw whatever you want here. Make sure it fits in the world rectangle. }
  2686. BEGIN
  2687.   MoveTo(100, 100);
  2688.   DrawString('testing...');  
  2689. END;
  2690. FUNCTION HiByte(word: INTEGER): Byte;
  2691. BEGIN
  2692.   HiByte := word DIV 256;
  2693. END;
  2694. PROCEDURE PrintStuff;
  2695. VAR
  2696.   thePrRec:   THPrint;
  2697.   thePrPort:  TPPrPort;
  2698.   theStatus:  TPrStatus;
  2699.   oldPort:    GrafPtr;
  2700.   theError:   OSErr;
  2701.   theVers:    INTEGER;
  2702.   NoGaps:     BOOLEAN;
  2703. BEGIN
  2704.   GetPort(oldPort);
  2705.   thePrRec := THPrint(NewHandle(SIZEOF(TPrint)));
  2706.   PrOpen;
  2707.   IF PrError = noErr THEN BEGIN
  2708.     PrintDefault(thePrRec);
  2709.     IF NOT PrStlDialog(thePrRec) THEN
  2710.       PrSetError(iPrAbort);
  2711.     IF NOT PrJobDialog(thePrRec) THEN
  2712.       PrSetError(iPrAbort);
  2713.     (* First, lock the handle down so we can do a cool with statement. *)
  2714.     HLock(Handle(thePrRec));
  2715.     IF PrError = noErr THEN
  2716.     WITH thePrRec^^ DO BEGIN
  2717.       (* Okay, now get device dependent.  We only want to do this if we *)
  2718.       (* know the selected printer driver supports it.                  *)
  2719.       IF (HiByte(prStl.wDev) = bDevImageWriter) OR
  2720.       (HiByte(prStl.wDev) = bDevImageWriterLQ) THEN BEGIN
  2721.         (* Now remember the state of the nogaps option.          *)
  2722.         NoGaps := BitTst(@prStl.wDev, 11);
  2723.         (* If NoGaps was selected, then turn it off until we PrOpenDoc.*)
  2724.         IF (NoGaps) THEN BitClr(@prStl.wDev, 11);
  2725.         (* If we're on the LQ driver, we need to copy the wDev into the*)
  2726.         (* PrintX array, or the LQ driver won't notice that it changed.*)
  2727.         IF (HiByte(prStl.wDev) = bDevImageWriterLQ) THEN
  2728.           PrintX[2] := prStl.wDev;
  2729.       END;
  2730.     END;
  2731.     HUnlock(Handle(thePrRec));
  2732.     (* Now open the document. *)
  2733.     thePrPort := PrOpenDoc(thePrRec, NIL, NIL);
  2734.     (* Now we need to see if the NoGaps option was selected. If it was *)
  2735.     (* then we turned it off before calling PrOpenDoc, so we need to   *)
  2736.     (* turn it back on. If wasn't selected, we won't do anything.      *)
  2737.     HLock(Handle(thePrRec));
  2738.     WITH thePrRec^^ DO BEGIN
  2739.       IF NoGaps AND
  2740.         (HiByte(prStl.wDev) = bDevImageWriter) OR
  2741.         (HiByte(prStl.wDev) = bDevImageWriterLQ) THEN BEGIN
  2742.         (* Turn it on for the ImageWriter. *)
  2743.         BitSet(@prStl.wDev, 11);
  2744.         (* Copy it over for the ImageWriter LQ. *)
  2745.         IF (HiByte(prStl.wDev) = bDevImageWriterLQ) THEN
  2746.           PrintX[2] := prStl.wDev;
  2747.       END;
  2748.     END;
  2749.     HUnlock(Handle(thePrRec));
  2750.     IF PrError = noErr THEN BEGIN
  2751.       PrOpenPage(thePrPort, NIL);
  2752.       IF PrError = noErr THEN BEGIN
  2753.         DrawStuff(thePrRec^^.prInfo.rPage);
  2754.       END;
  2755.       PrClosePage(thePrPort);
  2756.     END;
  2757.     PrCloseDoc(thePrPort);
  2758.     IF (thePrRec^^.prJob.bJDocLoop = bSpoolLoop) and (PrError = noErr) 
  2759.       THEN PrPicFile(thePrRec, NIL, NIL, NIL, theStatus);
  2760.   END;
  2761.   PrClose;
  2762.   DisposHandle(Handle(thePrRec));
  2763.   SetPort(oldPort);
  2764. END;
  2765. BEGIN
  2766.   InitGraf(@thePort);                          {initialize QuickDraw}
  2767.   InitFonts;                                   {initialize Font Manager}
  2768.   FlushEvents(everyEvent, 0); {call OS Event Mgr to discard}
  2769.                               {any previous events}
  2770.   InitWindows;                                 {initialize Window Manager}
  2771.   InitMenus;                                   {initialize Menu Manager}
  2772.   TEInit;                                      {initialize TextEdit}
  2773.   InitDialogs(NIL);                       {initialize Dialog Manager}
  2774.   InitCursor;            {call QuickDraw to make cursor (pointer) an arrow}
  2775.   PrintStuff;
  2776. END.
  2777. Update Macintosh color table if printing in color
  2778. Date Written:  5/3/89
  2779. Last reviewed:  6/14/93
  2780. I’m having trouble printing in color. When I copy a color image from a Macintosh offscreen pixmap to the printer, I get a black piece of paper. If I draw directly it comes out fine. What am I doing wrong?
  2781. ___
  2782. When you built your offscreen port and copied the color table from a GDevice, did you change the color table to reflect that the color table is now part of a pixmap? In a GDevice the color table’s value field is zero for all entries, but in a pixmap the value field represents the index value of each color in the table. If the color table has not been converted, printing won’t work properly.
  2783. PR 520 - PrintMonitor Q&As
  2784. Printing    
  2785. Revised by:    Developer Support Center    September 1993
  2786. Written by:    Developer Support Center    October 1990
  2787. This Technical Note contains a collection of Q&As relating to a specific topic—questions you’ve sent the Developer Support Center (DSC) along with answers from the DSC engineers. While DSC engineers have checked the Q&A content for accuracy, the Q&A Technical Notes don’t have the editing and organization of other Technical Notes. The Q&A function is to get new technical information and updates to you quickly, saving the polish for when the information migrates into reference manuals.
  2788. Q&As are now included with Technical Notes to make access to technical updates easier for you. If you have comments or suggestions about Q&A content or distribution, please let us know by sending an AppleLink to DEVFEEDBACK. Apple Partners may send technical questions about Q&A content to DEVSUPPORT for resolution.
  2789. New Q&As in this Technical Note:
  2790. Determining whether background printing is enabled
  2791. Determining whether background printing is enabled
  2792. 62755 MD JM dy 1
  2793. Date Written:  1/20/93
  2794. Last reviewed:  4/26/93
  2795. How can I tell whether background printing is enabled for the selected printer?
  2796. ___
  2797. There’s no procedure to determine whether the user has picked background printing because that’s not a standard Macintosh system software feature. Where it’s done, it’s implemented on a driver-by-driver basis, and each printer driver keeps track of it in a different way. Apple does it one way, Hewlett-Packard might do it another way, GCC a third way, and so on.
  2798. Since we don’t actually know how it’s done, and since Apple doesn’t guarantee its drivers will do it the same way in the future as they do now, we have no information to give you on how to determine this. Sorry to be the bearer of bad news.
  2799. Location for spool files under System 7.0
  2800. Date Written:  12/18/90
  2801. Last reviewed:  8/1/92
  2802. Is there a recommended location for printer driver writers to put their own spool files?
  2803. ___
  2804. Place it in the “PrintMonitor Documents” folder within a “personal spool” folder. PrintMonitor will ignore other folders and it will delete its spool file when it was done with it.
  2805. The biggest advantage with this approach is that all the spool files end up in the same location, which is probably the best solution for the native user.
  2806. There are a few cases when the folder might not be present (such as if the user has deleted it for some reason). Therefore, you should check to make sure that the folder is present before trying to add a file to it. If it is not present, be sure to create it with the exact name; otherwise, PrintMonitor will not be able to find it and will create a second folder with a different name, possibly confusing the native user. Folder management is relatively straightforward with the addition of the “Folder Manager” to System 7.0. The Finder chapter in Inside Macintosh Volume VI contains the details about using it.
  2807. Determining whether background printing is turned on
  2808. Date Written:  2/5/92
  2809. Last reviewed:  8/1/92
  2810. I need to know whether the currently chosen printer driver—that I’m about to print to—is going to be doing background printing or not. The user interface of our application is somewhat different, depending on this. Currently, I check the driver’s file type to see whether it’s network- or local-attached, generalizing “network = LaserWriter = background capable” and “direct = ImageWriter = foreground only,” but I know this isn’t always correct, because a variety of direct-connect printer drivers now support background printing. What I really need is a way to check specifically for background printing being turned on. Is there a safe and driver-independent way to check this?
  2811. ___
  2812. No, there’s absolutely no safe and driver-independent way to do this. Although Apple uses PrintMonitor for all background printing, it’s not designed for third-party products to hook into it. The “background printing” internals aren’t documented because changing that outside an individual printer driver may not give the driver all the information it needs to correctly print in the background. Also, third parties have to implement their own background printing schemes, and there’s absolutely no way to know how they’re storing the choice on whether or not to print in the background.
  2813. If your user interface is substantially different, you may need to require your users to enable background printing in your application as well as in the Chooser. This isn’t exactly friendly, but since there’s no mechanism for applications to communicate with printer drivers to find out about background printing, it’s pretty much your only choice.
  2814. You’re right, checking a driver’s file type to see whether it’s network- or local-attached is not a good solution. StyleWriters and LaserWriter LS printers print in the background but don’t use a network. Some third-party laser printers support AppleTalk but not background printing.
  2815. Turning Macintosh background printing on and off
  2816. Date Written:  3/25/92
  2817. Last reviewed:  6/14/93
  2818. Someone has requested that we do an extension for our application to turn background printing on and off. Can you tell me how to do this?
  2819. ___
  2820. Unfortunately, DTS can’t tell you how to turn background printing on and off, for the following reasons:
  2821. 1. Apple’s mechanism for background printing (PrintMonitor) is at this time only available to Apple’s printer drivers. How Apple’s printer drivers store the background printing choice is private because Engineering has changed it in the past and might need to change it again.
  2822. 2. Since all third-party printer drivers that do background printing have to do it their own way, they all have to find their own ways of recording the “background printing” choice, such as storing the information in resources like the PAPA resource. Since there are no guidelines for recording background printing options, DTS cannot recommend a method which will work with all drivers.
  2823. For these reasons, and to avoid possible Human Interface conflicts, background printing control is best left to the user.
  2824. Macintosh PicComments and background printing
  2825. Date Written:  5/3/89
  2826. Last reviewed:  6/14/93
  2827. My Macintosh application prints fine when Background Printing is disabled, but doesn’t print or prints blank pages when Background Printing is enabled. Why?
  2828. ___
  2829. The Printing Manager gets execution time by replacing the grafProcs of the Printing Manager GrafPort (returned from the PrOpenDoc call). This GrafPort is created by the PrOpenDoc call, and is reinitialized by every call to PrOpenPage. On the LaserWriter driver with Background Printing enabled, this reinitialization causes the clipping region of the port to be set to (0,0,0,0). On the next call to StdLine or StdText, for example, the Printing Manager notices the zeroed clipping region, and sets it to the rectangle specified by prInfo.rPage in the print record. If your application prints its documents with PostScript using PicComments, the Printing Manager never gets a chance to define the clipping region. All of your PostScript code is sent to the LaserWriter and executed, but the results are clipped to (0,0,0,0). To work around this problem, you must call at least one Quickdraw drawing routine at the beginning of each page. The following is frequently used:
  2830.     PrOpenPage(...);
  2831.     MoveTo(-32000, -32000);
  2832.     Line(0, 0);
  2833.     { PostScript code here }
  2834.     PrClosePage(...);
  2835. The MoveTo is needed so that the line is drawn outside of the imageable area of the page, and thus is invisible. The Line call calls the Printing Manager’s version of the StdLine procedure, which defines the clipping region for the port. All subsequent PostScript code will be clipped correctly. Since PrOpenPage resets the clipping region, the MoveTo/Line combination must be done after each call to PrOpenPage.
  2836. SetOrigin and background printing
  2837. Date Written:  1/1/90
  2838. Last reviewed:  6/14/93
  2839. I have noticed PostScript graphics printing in different locations depending on whether or not Background printing is enabled on the Macintosh. What causes this?
  2840. ___
  2841. In LaserWriter 4.0 - 5.2, SetOrigin is handled differently when Background printing is enabled. The method used by these drivers is described below:
  2842. Background Printing DISABLED: The application calls SetOrigin, and QuickDraw responds to the call by adjusting the portRect of the Print Manager’s GrafPort. Since SetOrigin does not cause any grafProcs to run, the Printing Manager doesn’t see this change until the next QuickDraw drawing operation such as DrawString or LineTo. At that time, the Printing Manager notices the change in the portRect, and updates its internal origin. All QuickDraw graphics are now localized to the new origin. All PostScript graphics will also get the localization to the new origin.
  2843. Background Printing ENABLED: Because QuickDraw is playing back a picture that was spooled earlier, it handles calls to SetOrigin a little differently. When the SetOrigin call is encountered in a DrawPicture call, the portRect of the GrafPort is NOT updated. Instead, QuickDraw keeps the current origin cached, and offsets each graphic on the fly. Since the portRect was not modified, the Printing Manager does not see the SetOrigin call. Although all QuickDraw objects are still localized correctly (by QuickDraw), PostScript graphics do not move to the new origin. Instead, the application localizes the coordinates of its PostScript graphics. You could also use the technique documented in the Technical Note “Position-Independent PostScript.”
  2844. The implementation of the SetOrigin (IM I:166) and ClipRect (IM I:167) calls has been revised in LaserWriter 6.0. This is a general description of those changes:
  2845. LaserWriter 6.0: Both QuickDraw and PostScript coordinates are offset with respect to the origin set by SetOrigin. The driver now inserts a picture comment into the spool file so that the Print Monitor knows that the origin was changed during spooling.
  2846. Since applications must support versions of the LaserWriter driver other than 6.0, they should still use the method described in this Tech Note to make sure their PostScript is position-independent.
  2847. X-Ref:
  2848. DTS Macintosh Technical Note “Position-Independent PostScript”
  2849. Macintosh spool file formats aren’t available
  2850. Date Written:  1/1/90
  2851. Last reviewed:  8/1/92
  2852. What is file format of Macintosh Printing Manager and LaserShare spool files?
  2853. ___
  2854. Unfortunately, the formats for these files are not currently available, and it is doubtful that they will be made available in the future. Whenever new features are added to LaserShare, the Printing Manager, or other parts of the Macintosh toolbox, it’s not uncommon for these spool file formats to be affected. If the file format were published, and essentially frozen, it would be much harder for engineering to add features.
  2855. PR 525 - QuickDraw GX Printing Q&As
  2856. Printing    
  2857. Revised by:    Developer Support Center    September 1993
  2858. Written by:    Developer Support Center    October 1990
  2859. This Technical Note contains a collection of Q&As relating to a specific topic—questions you’ve sent the Developer Support Center (DSC) along with answers from the DSC engineers. While DSC engineers have checked the Q&A content for accuracy, the Q&A Technical Notes don’t have the editing and organization of other Technical Notes. The Q&A function is to get new technical information and updates to you quickly, saving the polish for when the information migrates into reference manuals.
  2860. Q&As are now included with Technical Notes to make access to technical updates easier for you. If you have comments or suggestions about Q&A content or distribution, please let us know by sending an AppleLink to DEVFEEDBACK. Apple Partners may send technical questions about Q&A content to DEVSUPPORT for resolution.
  2861. New Q&As for this month:
  2862. QuickDraw GX printing extensions and creator types
  2863. NewMessageGlobals and global data
  2864. QuickDraw GX LaserWriter driver produces “portable” PostScript
  2865. QuickDraw GX PostScript Level 2 features used
  2866. QuickDraw GX printer drivers and color option
  2867. QuickDraw GX printing extensions and creator types
  2868. Date Written:   5/3/93
  2869. Last reviewed: 7/2/93
  2870. A QuickDraw GX printing extension I’ve already written works fine, but when I install my latest creation, it doesn’t show up in the print dialog—only my old printing extension does. Both extensions are the same except for a few lines of code in their gxDespoolPage message overrides. What’s going on?
  2871. ___
  2872. Your printing extensions shouldn’t have the same creator type. QuickDraw GX requires unique creator types for drivers and printing extensions, just as the Finder does for applications. A creator type must be unique because QuickDraw GX uses it to build its chain of message handlers. If two printing extensions have the same creator, there’s no way to determine which is which in the chain. You can register creator types for your printer drivers and printing extensions with the Developer Support Center (AppleLink DEVSUPPORT).
  2873. NewMessageGlobals and global data
  2874. Date Written:  2/1/93
  2875. Last reviewed: 7/2/93
  2876. Why can’t I get NewMessageGlobals to work in my gxInitialize message for my QuickDraw GX printing extension? The global data I try to initialize isn’t being accessed correctly.
  2877. ___
  2878. You shouldn’t call NewMessageGlobals from any routine in which you access your global data. Otherwise, because of optimization that your compiler may perform, the data references can be invalid. Instead, use an approach like this:
  2879. extern long A5Size(void);
  2880. extern void A5Init(void *);
  2881. typedef    struct GlobalType {
  2882.     StringHandle    aString;
  2883. } GlobalType;
  2884. GlobalType    myGlobals;
  2885. /* This routine sets the initial values of our global data. */
  2886. OSErr InitGlobalData()
  2887. {
  2888.     OSErr    err;
  2889.     // Initialize our globals.
  2890.     myGlobals.aString = GetString(r_myStringID);
  2891.     err = ResError();
  2892.     if (!err) DetachResource(myGlobals.aString);
  2893.     return err;
  2894. }
  2895. /* Our override for the gxInitialize message. */
  2896. OSErr MyInitialize()
  2897. {
  2898.     OSErr    err;
  2899.     // Create an A5 world, then go initialize our global data.
  2900.     err = NewMessageGlobals(A5Size(), A5Init());
  2901.     if (!err) err = InitGlobalData();
  2902.     return err;
  2903. }
  2904. A detailed explanation of the problem accompanies the Kabooms printing extension sample on the Developer CD.
  2905. QuickDraw GX LaserWriter driver produces “portable” PostScript
  2906. Date Written:  11/17/92
  2907. Last reviewed: 7/2/93
  2908. When a QuickDraw GX PostScript printer driver generates a file, will it work for Level 1 and Level 2 printers?
  2909. ___
  2910. The LaserWriter driver bundled with QuickDraw GX produces a flavor of PostScript that we call “portable.” This flavor is meant to work on the widest range of printing devices, be they Level 1 or 2, color or black and white.
  2911. QuickDraw GX PostScript Level 2 features used
  2912. Date Written:  11/17/92
  2913. Last reviewed: 7/2/93
  2914. What PostScript Level 2 features does the QuickDraw GX printing mechanism take advantage of?
  2915. ___
  2916. The Level 2 features used in QuickDraw GX mostly have to do with patterns, text, and bitmaps:
  2917. •    QuickDraw GX patterns are converted into Level 2 pattern dictionaries when going to a Level 2 printer. The actual PostScript code emitted by the driver differs little with respect to patterns when going to Level 1 or Level 2. However, the procedures defined in the header do something entirely different on a Level 2 printer.
  2918. •    Line layout in QuickDraw GX takes advantage of the xshow, yshow, and xyshow operators when it makes sense to do so.
  2919. •    The Level 2 rectangle operators are used in Level 2, though this happens in the procedures defined in the header rather than in PostScript code from the driver.
  2920. •    On Level 2 printers, the indexed color spaces are used for printing bitmaps up to eight bits deep.
  2921. •    The plan is to use Level 2 device-independent color when possible.
  2922. QuickDraw GX printer drivers and color option
  2923. Date Written:   9/14/92
  2924. Last reviewed: 7/2/93
  2925. The LaserWriter driver before the QuickDraw GX version has an option to print in Color/Grayscale or Black & White. Why isn’t this option in the QuickDraw GX LaserWriter driver?
  2926. ___
  2927. The Color/Grayscale option was added to the LaserWriter driver only for compatibility reasons. At the time, some applications couldn’t deal with the color option (specifically with cGrafPorts), so a Black & White mode was also provided. The Black & White mode exhibited the same functionality as the earlier LaserWriter driver 5.2.
  2928. Because most applications are color compatible now, the option was removed from the QuickDraw GX printer drivers. Some people reported that the option let them print faster when they chose Black & White. This was true because of quirks in the earlier LaserWriter driver version. Under QuickDraw GX, this shouldn’t be a problem. If it turns out to be a problem for your driver, you could incorporate black-and-white threshold printing into your “rough draft mode” code. The QuickDraw GX LaserWriter driver always prints in color.
  2929. T◊#ˇ ˇˇˇˇ#◊†Ç 
  2930. /ZÅ#
  2931.     0Ià:µú9"{    ˇˇˇˇˇˇˇˇ#†ƒ°d
  2932. ONLNf˛†å°d1drw2…-·_ġˇˇˇˇˇè°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˙ó@†ò,Times
  2933. .R…R…+]BNew Technical Notes†ô°ddrw2:°„†ó°d1drw2eÙġˇˇˇˇˇP°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚ÄE¿†ò
  2934. ({ïDeveloper Support†ô°ddrw2:°„†ó°d`drw2-ÔˇˇˇˇˇˇKÔ- Z  ffZ°d1drw2 ¿˙ÈˇˇˇˇˇˇK°ñ x°ddrw2:°ddrw2:$°d4drw2:0°öˇÙĆò
  2935. 0(UÔ†ô°ddrw2:°„†ó°d1drw2ÔÊ˙ˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:    °öˇ˝Ä†ò
  2936.     +&    ®†ô°ddrw2:°„†ó°d1drw2Â-¯yˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚Ä%†ò
  2937. (Z\    Macintosh†ô°ddrw2:°„†ó†ç°ddrw2D†É
  2938. IR.°dONLNdn<ÅÌ(õZPR 1 - Color Printing
  2939. °dONLNdÄ<ès*Printing
  2940. °dONLNd õ<ßt* Revised by:°dONLNd,õÑßÛ)HScott "ZZ" Zimmerman°dONLNdAõæß˛(√‹ January 1988°dONLNdQß≈≥˛+
  2941. March 1988°dONLNd\≥<øq(€Z Written by:°dONLNdh≥Ñø–)HGinger Jernigan°dONLNdx≥∏ø˛(€÷
  2942. February 1986°dONLNdÜÀ<◊F(ÛZ9This discusses color printing in a Macintosh application. X°dONLNd¿<¸*%\Whereas the original eight-color model of QuickDraw was sufficient for printing in color on °dONLNd¸˛(the°dONLNd ¸<ë($ZImageWriter II, °dONLNd0¸ë˛)UAthe introduction of Color QuickDraw has created the need for more°dONLNdr<–(0Zsophisticated printing methods.°dONLNdí <,w*BThe first section describes using the eight-color QuickDraw model °dONLNd‘ w,˛(Hïwith the ImageWriter II and°dONLNd,<8n(TZ=ImageWriter LQ drivers. Since the current Print Manager does °dONLNd-,n8˛(Tånot support Color GrafPorts,°dONLNdJ8<Dè(`ZHthe eight-color model is the only method available for the ImageWriters.°dONLNdìP<\Ω*NThe next section describes a technique that can be used for printing halftone °dONLNd·PΩ\˛(x€ images using°dONLNdÓ\<h"(ÑZ2PostScript (when it is available). Also described °dONLNd \"h˛)Ê-is a device independent technique for sending°dONLNdNh<tõ(êZthe PostScript data. °dONLNdchõt˛)_JThis technique can be used on any LaserWriter driver 3.0 or later. It will°dONLNdÆt<ÄW(úZ;work with all LaserWriters except the the LaserWriter IISC.°dONLNdÍå<ò*4It is very likely that better color support will be °dONLNdåò˛)‡/added to the Print Manager in the future. Until°dONLNdNò<§(¿Z+then, these are the best methods available.
  2943. °dONLNdzº<À *'Part 1, ImageWriters
  2944. °dONLNdè◊<„Í*$The ImageWriter drivers are capable °dONLNd≥◊Í„˛)Æ:of generating each of the eight standard colors defined in°dONLNdÓ„<Ôı( Z%QuickDraw by the following constants:,
  2945. Courier°dONLNd˚`¶+$
  2946. whiteColor°dONLNd!`¶*
  2947. blackColor°dONLNd-`ò* redColor°dONLNd7`+¶*
  2948. greenColor°dONLNdC+`7ü*     blueColor°dONLNdN7`Cü*     cyanColor°dONLNdYC`O¥* magentaColor°dONLNdgO`[≠* yellowColor°dONLNdsg<sÏ(èZXTo generate color all you need to do is set the foreground and background colors before °dONLNdÀgÏs˛(è
  2949. you°dONLNdœs<t(õZCbegin drawing (initially they are set to blackColor foreground and °dONLNdst˛(õíwhiteColor background). To°dONLNd-Ä<å˙(®Z(do this you call the QuickDraw routines °dONLNdU˙ã9)æ    ForeColor°dONLNd^Ä9åR)? and °dONLNdcRãë)    BackColor°dONLNdlÄëå·)? as described in °dONLNd}Ä·å˛)PInside ¡X¡
  2950. (÷ZPR 1 - Color Printing(÷1) of 4(ÏZM.PR.ColorPrintingˇ°¿Ù%%DSIDICT:_cv
  2951. currentdict /bu known {bu}if
  2952. userdict /_cv known not{userdict /_cv 30 dict put}if
  2953. _cv begin
  2954. /bdf{bind def}bind def
  2955. currentscreen/cs exch def/ca exch def/cf exch def
  2956. /setcmykcolor where{/setcmykcolor get /cvcmyk exch def}{/cvcmyk{1 sub 4 1 roll 3{3 index add neg dup 0 lt{pop 0}if 3 1 roll}repeat setrgbcolor pop}bdf }ifelse
  2957. /ss{//cf //ca //cs setscreen}bdf
  2958. /stg{ss setgray}bdf
  2959. /strgb{ss setrgbcolor}bdf
  2960. /stcmyk{ss cvcmyk}bdf
  2961. /min1{dup 0 eq{pop 1}if}bdf
  2962. end
  2963. currentdict /bn known {bn}if
  2964. †ø◊#ˇ ˇˇˇˇ#◊ 
  2965. IR,Times
  2966. .+6-Macintosh Technical Notes /4/˘
  2967. °dONLNd)I*    Macintosh°dONLNd    I)_)1. If °dONLNd_)⁄)Fyou are using QuickDraw pictures, make sure you set the foreground and°dONLNdU*6¡(R6"background colors before you call ,
  2968. Courier°dONLNdw)¡5)© ClosePicture°dONLNdÉ*6g)T so that they are °dONLNdï*g6⁄)Rrecorded in the picture.°dONLNdÆ7C∞(_6"Setting the colors before calling °dONLNd–6∞B˝)ò DrawPicture°dONLNd€7˝CC)M doesn’t work.°dONLNdÍP\(x66The drivers also recognize two of the transfer modes: °dONLNd O[G)˛srcCopy°dONLNd'PG\J)1 °dONLNd(PJ\_)and °dONLNd,O_[Ç)srcOr°dONLNd1PÇ\⁄)#. The effect of the°dONLNdE\hZ(Ñ6other transfer °dONLNdT\Zh⁄)BNmodes is not well defined and has not been tested. It may be best to stay away°dONLNd£htM(ê6
  2969. from them.°dONLNdÆÄåD*Caveats°dONLNd∂ò§Ñ*GWhen printing a large area of more than one color you will encounter a °dONLNd˝òѧ⁄(¿¢problem with the°dONLNd§∞–(Ã6'ribbon. When you print a large area of °dONLNd5§–∞⁄)∏8one color, the printer’s pins pick up the color from the°dONLNdn∞º>(ÿ6back of °dONLNdv∞>º⁄)&Vthe ribbon. When another large area of color is printed, the pins deposit the previous°dONLNdÕº»3(‰6color °dONLNd”º3»⁄)Yonto the back of the ribbon. Eventually the first color will come through to the front of°dONLNd-»‘#(68the ribbon, contaminating the second color. You can get °dONLNde»#‘⁄(A'the same kind of effect if you set, for°dONLNd瑇Œ(¸6[example, a foreground color of yellow and a background color of blue. The ribbon will pick °dONLNdË‘Œ‡⁄(¸Ïup°dONLNd·Ï@(6@the blue as it tries to print yellow on top of it. This problem °dONLNd+‡@Ï⁄(^"is partially alleviated in the 2.3°dONLNdNϯq(6Jversion of the ImageWriter driver by using a different printing technique.°dONLNdô*3The ribbon goes through the printer rather quickly °dONLNdÃ⁄)Ô*when printing large areas. When the ribbon°dONLNd˜?(86>comes through the second time the colors don’t look too great.
  2970. °dONLNd64C£*'Part 2, LaserWriters°dONLNdKO^ì*Using the PostScript ‘image’ Operator to Print Halftones
  2971. °dONLNdÑjvi*
  2972. About ‘image’°dONLNdíÇé‘*&The PostScript image operator is used °dONLNd∏Ç‘é⁄)º2to send Bitmaps or Pixmaps to the LaserWriter. The°dONLNdÎéö(∂66image operator can handle depths from 1 to 8 bits per °dONLNd!éö⁄)˛(pixel. Our current LaserWriters can only°dONLNdJö¶P(¬6Bimage about twenty shades of gray, but the printed page will look °dONLNdåöP¶⁄(¬nlike there’s more. Being that°dONLNd™¶≤¢(Œ6Vthe image operator is still a PostScript operator, it expects its data in the form of °dONLNd¶¢≤⁄(Œ¿ hexidecimal°dONLNd ≤æ¬(⁄6$bytes. The bytes are represented by °dONLNd0≤¬æ⁄)™7two ASCII characters(0-9,A-F). The image operator takes°dONLNdhæ i(Ê6these parameters:
  2973.     °dONLNd{÷<·+$(width  height  depth  matrix  image-data
  2974. °dONLNd§Ï¯g(6?The first three are the width, height, and depth of the image, °dONLNd„Ïg¯⁄(Öand the matrix is the°dONLNd˘¯ñ( 6transformation matrix to °dONLNd¯ñt)~*be applied to the current matrix. See the °dONLNd<¯t⁄)fiPostScript Language°dONLNdPn(,6Reference Manual°dONLNd`nY)V/ for more information. The image data is where °dONLNdèY⁄)Îthe actual hex data should°dONLNd™7(86?go. Instead of inserting the data between the first parameters °dONLNdÈ7⁄(8U$and the image operator itself, it is°dONLNd    (æ(D6[better to use a small, PostScript procedure to read the data starting from right after the °dONLNd    iæ(⁄(D‹image°dONLNd    o(4Ñ(P6operator. For example:
  2975.     °dONLNd    á@<K√+$ 480 8 [640 0 0 480 0 0]°dONLNd    §J<U˙*
  2976. &{currentfile picstr readhexstring pop}°dONLNd    ÃT<_U*
  2977. image°dONLNd    ”^<i√*
  2978. FF 00 FF 00 FF 00 FF 00 ...
  2979. °dONLNd    ÔtÄO(ú6CIn the above example, the width of the image is 640, the height is °dONLNd
  2980. 2tOÄ⁄(úm480, and the depth is 8. The°dONLNd
  2981. OÄåΩ(®6Zmatrix (enclosed in brackets) is setup to draw the image starting at QuickDraw’s 0,0 (top °dONLNd
  2982. ©ÄΩå⁄(®€left of ¡4¡˘
  2983. (÷62) of 4(÷üPR 1 - Color Printing+M.PR.ColorPrintingˇÃ◊#ˇ ˇˇˇˇ#◊ 
  2984. IR,Times
  2985. .+Z-Developer Support Center(-Ï
  2986. March 1988 /X/
  2987. °dONLNd<)’(EZ page), and with no scaling. The °dONLNd ’)˛)ô>PostScript code (enclosed in braces) is not executed. Instead,°dONLNd_)<5É(QZit is passed to °dONLNdo)É5˛)GOthe image operator, and the image operator will call it repeatedly until it has°dONLNdø5<AÁ(]Z"enough data to draw the image. In °dONLNd·5ÁA˛)´7this case, it will be expecting 640*480 bytes. When the°dONLNdA<MH(iZ:image operator calls the procedure, it does the following:°dONLNdTYNeX+1.°dONLNdWY`e+)+Pushes the current file which in this case °dONLNdÇY+e⁄)À#is the stream of data coming to the°dONLNd¶e`q∂(ç~ILaserWriter over AppleTalk. This is the first parameter to readhexstring.°dONLNd}NâX(•l2.°dONLNdÛ}`â)*Next picstr is pushed. picstr is a string °dONLNd}â⁄)π'variable defined to hold one row of hex°dONLNdEâ`ï&(±~-data. The PostScript to create the picstr is:,
  2988. Courier
  2989.     °dONLNdu°Ñ¨œ+$/picstr 640 def
  2990. °dONLNdÖ∑N√X(fll3.°dONLNdà∑`√.)+Now readhexstring is called to fill picstr °dONLNd≥∑.√⁄)Œ#with data from the current file. It°dONLNd◊√`œƒ(Î~Kbegins reading bytes which are the characters following the image operator.°dONLNd#€NÁX(l4.°dONLNd&€`Á∞)BSince readhexstring leaves both the string we want, and a boolean °dONLNdh€∞Á’(Œthat we°dONLNdpÁ`Û    (~#don’t want on the stack, we do one °dONLNdìÁ    Û’)©*pop to kill of the boolean. Now the string°dONLNdæÛ`ˇ+(~-is left behind for the image operator to use.°dONLNdÏ <˚(3Z'So using the above PostScript code you °dONLNd ˚˛)ø8can easily print an image. Just fill in the width height°dONLNdL<#•(?ZKand depth, and send the hex data immediately following the PostScript code.°dONLNdò/<;Ω*Setting Up for ‘image’°dONLNdØG<S∏*Most of the users of this °dONLNd…G∏S˛)|>technique are going to want to print a Color QuickDraw PixMap.°dONLNdS<_Ã({ZAlthough the image command °dONLNd#SÃ_˛)êBdoes a lot of the work for you, there are still a couple of tricks°dONLNdf_<kˆ(áZ%that are recommended for performance.°dONLNdåw<É›*Assume the Maximum Depth°dONLNd•è<õ6*6Since the current version of the image operator has a °dONLNd€è6õ˛)˙)maximum depth of 8 bits/pixel, it is wise°dONLNdõ<ߌ(√ZTto convert the source image to the same depth before imaging. This can be done very °dONLNdYõŒß˛(√Ï    simply by°dONLNdcß<≥9(œZ9using an offscreen GrafPort that is set to 8 bits/pixel, °dONLNdúß9≥˛)˝'and then using CopyBits to do the depth°dONLNdƒ≥<ø¯(€ZUconversion for you. This will do a nice job of converting lower resolution images to °dONLNd≥¯ø˛(€8°dONLNdø<Àk(ÁZ bits/pixel.°dONLNd'◊<„¨*Build a Color Table°dONLNd;Ô<˚œ*An 8 bit deep image can only °dONLNdXÔœ˚˛)ì=use 256 colors. Since the image that you are starting with is°dONLNdñ˚<·(#Z"probably color, and the image you °dONLNd∏˚·˛)•<get will be grayscale, you need to convert the colors in the°dONLNdı<
  2991. (/Z-source color table into PostScript grayscale °dONLNd"
  2992. ˛)Œ3values. This is actually easy to do using the Color°dONLNdV<P(;Z<Manager. First create a table that can hold 512 bytes. This °dONLNdíP˛(;n$is 2 bytes for each color value from°dONLNd∑<+(GZ/0 to 255. Since PostScript wants the values in °dONLNdÊ+˛)‹.ASCII, you need two characters for each pixel.°dONLNd    +<7~(SZDNow loop through the colors in the color table. Call Index2Color to °dONLNd    Y+~7˛(Súget the real RGB color for°dONLNd    t7<C˚(_Z%that index, and then call RGB2HSL to °dONLNd    ô7˚C˛)ø2convert the RGB color into a luminance value. This°dONLNd    ÃC<Om(kZ value will °dONLNd    ◊CmO˛)1Qbe expressed as a SmallFract which can then be scaled into a value from 0 to 255.°dONLNd
  2993. )O<[Ω(wZThis value should then be °dONLNd
  2994. COΩ[˛)ÅAconverted to ASCII, and stored at the appropriate location in the°dONLNd
  2995. Ö[<gÙ(ÉZ^table. When you are done, you should be able to use a pixel value as an index into your table °dONLNd
  2996. „[Ùg˛(Éof°dONLNd
  2997. Êg<sÔ(èZ]PostScript color values. For each pixel in the image, send two characters to the LaserWriter. ¡X¡
  2998. *GPR 1 - Color Printing(÷3) of 4(ÏZM.PR.ColorPrintingˇ\◊#ˇ ˇˇˇˇ#◊ 
  2999. IR,Times
  3000. .+6-Macintosh Technical Notes /4/˘
  3001. °dONLNd)x*Sending the Data°dONLNd5AÎ*/Once you have set up the color table, all that °dONLNd@5ÎA⁄)”4left to do is to loop through all of the pixels, and°dONLNduAMŒ(i6(send their PostScript representation to °dONLNdùAŒM⁄)∂7the LaserWriter. There are a couple of ways to do this.°dONLNd’MY (u6:First is to use the low-level Print Manager interface and °dONLNdM Y⁄(u>&stream the PostScript using the stdBuf°dONLNd6Ye˙(Å6-PrCtlCall. Although this seems like it would °dONLNdcY˙e⁄)‚-be the fastest way, the latest version of the°dONLNdëeqL(ç6?LaserWriter driver (5.0) converts all low-level calls to their °dONLNd–eLq⁄(çjhigh level equivalent before°dONLNdÌq}ı(ô6/executing them. Because of this, the low-level °dONLNdqı}⁄)›2interface is no longer faster than the high level.°dONLNdO}â∑(•6!In an FKEY I have written, I use °dONLNdp}∑â⁄)ü=the high-level Print Manager interface, and send the data via°dONLNdÆâïf(±6@the PostScriptHandle PicComment. This way, I can buffer a large °dONLNdÓâfï⁄(±Ñamount of data, before°dONLNdï°¸(Ω62actually sending it. Using this technique, I have °dONLNd7︰⁄)‰-been able to image a Mac II screen in about 5°dONLNde°≠î(…6Mminutes on a LaserWriter Plus, and about 1.5 minutes on a LaserWriter II NTX.°dONLNd≥—›Ç*0Further Reference: ¸4¸˘°dONLNdΔfi*Í.+
  3002. •°dONLNd»fi<Ír)    QuickDraw°dONLNd“Í*ˆ.(H•°dONLNd‘Í<ˆ£)The Printing Manager°dONLNdȈ*.(H•°dONLNdΈ<G)3PostScript Language Reference Manual, Adobe Systems ¡4¡˘
  3003. (÷64) of 4(÷üPR 1 - Color Printing+M.PR.ColorPrintingˇû◊#ˇ ˇˇˇˇ#◊†Ç 
  3004. /ZÅ#
  3005.     0Ià:µú9"{    ˇˇˇˇˇˇˇˇ#†ƒ°d
  3006. ONLNf˛†å°d1drw2…-·_ġˇˇˇˇˇè°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˙ó@†ò,Times
  3007. .R…R…+]BNew Technical Notes†ô°ddrw2:°„†ó°d1drw2eÙġˇˇˇˇˇP°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚ÄE¿†ò
  3008. ({ïDeveloper Support†ô°ddrw2:°„†ó°d`drw2-ÔˇˇˇˇˇˇKÔ- Z  ffZ°d1drw2 ¿˙ÈˇˇˇˇˇˇK°ñ x°ddrw2:°ddrw2:$°d4drw2:0°öˇÙĆò
  3009. 0(UÔ†ô°ddrw2:°„†ó°d1drw2ÔÊ˙ˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:    °öˇ˝Ä†ò
  3010.     +&    ®†ô°ddrw2:°„†ó°d1drw2Â-¯yˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚Ä%†ò
  3011. (Z\    Macintosh†ô°ddrw2:°„†ó†ç°ddrw2D†É
  3012. IR.°dONLNdn<Åc(õZ"PR 2 - Device-Independent Printing
  3013. °dONLNd#Ä<ès*Printing
  3014. °dONLNd-õ<ßt* Revised by:°dONLNd:õ≈߲(√„
  3015. March 1988°dONLNdEß<≥q(œZ Written by:°dONLNdQßÑ≥”)HGinger Jernigan °dONLNdbߌ≥˛(œÏMay 1987 fiXfi°dONLNdkÃ<ÿƒ(ÙZThe Printing Manager was °dONLNdÑÃÿ˛)à=designed to give Macintosh applications a device- independent°dONLNd¬ÿ<‰õ(Zmethod of printing, °dONLNd÷ÿõ‰¿)_but we °dONLNd›ÿ¿‰÷)%have°dONLNd·ÿ÷‰˛)< provided device-dependent information, such as the contents°dONLNd‰<É( ZEof the print record. Due to the large number of printer-type drivers °dONLNdc‰É˛( °becoming available (even°dONLNd|<¸(Z-for non-printer devices) device independence °dONLNd©¸˛)◊/is more necessary than ever. What this means to°dONLNdŸ¸<W($Zyou, °dONLNdfi¸W˛)Ras a developer, is that we will no longer be providing (or supporting) information°dONLNd1<((0Z5regarding the internal structure of the print record.°dONLNdh <,Ÿ*XWe realize that there are situations where the application may know the best method for °dONLNd¿ Ÿ,˛(H˜printing°dONLNd…,<8‘(TZa particular document and may °dONLNdÁ,‘8˛)ò9want to bypass our dialogs. Unfortunately, using your own°dONLNd!8<D‡(`Z\dialogs or not using the dialogs at all, requires setting the necessary fields in the print °dONLNd}8‡D˛(`˛record°dONLNdÑD<P(lZ)yourself. There are a number of problems:°dONLNdÆ\NhR+•°dONLNd∞\[hfi)
  3016. KMany of the fields in the print record are undocumented, and, as we change °dONLNd˚\fihÏ(Ѹthe°dONLNdˇh[tå(êy=internal architecture of the Printing Manager to accommodate °dONLNd<håtÏ(ê™new devices, those°dONLNdOt[Ä(úy)undocumented fields are likely to change.°dONLNdyåNòR(¥l•°dONLNd{å[ò)
  3017. "Each driver uses the private, and °dONLNdùåòÏ)©.many of the public, fields in the print record°dONLNdÃò[§J(¿y2differently.  The implications are that you would °dONLNd˛òJ§Ï)Ôneed intimate knowledge of how°dONLNd§[∞ñ(Ãyeach field is °dONLNd+§ñ∞Ï);Gused by  each available driver, and you would have to set the fields in°dONLNds∞[ºè(ÿy the record °dONLNd~∞躿)4 differently°dONLNdâ∞¿º)1 depending on the °dONLNdõ∞ºÏ)[)driver chosen. As the number of available°dONLNd≈º[»ó(‰yBprinter-type drivers increases, this can become a cumbersome task.
  3018. °dONLNd‡<Ôz( ZSummary
  3019. °dONLNd˚<«*To be compatible with future °dONLNd-˚«˛)ãFprinter-like devices, it is essential that your application print in a°dONLNdt<ú(/Zdevice-independent °dONLNdáú˛)`Fmanner. Avoid testing undocumented fields, setting fields in the print°dONLNdŒ<^(;Zrecord °dONLNd’^˛)"Tdirectly and bypassing the existing print dialogs. Use the Printing Manager dialogs,,
  3020. Courier°dONLNd*<+ê(HZ PrintDefault°dONLNd6 ê,ß)T and °dONLNd;ß+Ì)
  3021. PrValidate°dONLNdE Ì,ç)F$ to set up the print record for you.°dONLNdjP<\¶(xZFurther Reference: {X{°dONLNd}]NiR+
  3022. •°dONLNd]`i«)The Printing Manager ¡X¡
  3023. (÷Z"PR 2 - Device-Independent Printing(÷1) of 1(ÏZM.PR.DeviceIndependentPrintingˇ°¿Ù%%DSIDICT:_cv
  3024. currentdict /bu known {bu}if
  3025. userdict /_cv known not{userdict /_cv 30 dict put}if
  3026. _cv begin
  3027. /bdf{bind def}bind def
  3028. currentscreen/cs exch def/ca exch def/cf exch def
  3029. /setcmykcolor where{/setcmykcolor get /cvcmyk exch def}{/cvcmyk{1 sub 4 1 roll 3{3 index add neg dup 0 lt{pop 0}if 3 1 roll}repeat setrgbcolor pop}bdf }ifelse
  3030. /ss{//cf //ca //cs setscreen}bdf
  3031. /stg{ss setgray}bdf
  3032. /strgb{ss setrgbcolor}bdf
  3033. /stcmyk{ss cvcmyk}bdf
  3034. /min1{dup 0 eq{pop 1}if}bdf
  3035. end
  3036. currentdict /bn known {bn}if
  3037. †øT◊#ˇ ˇˇˇˇ#◊†Ç 
  3038. /ZÅ#
  3039.     0Ià:µú9"{    ˇˇˇˇˇˇˇˇ#†ƒ°d
  3040. ONLNf˛†å°d1drw2…-·_ġˇˇˇˇˇè°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˙ó@†ò,Times
  3041. .R…R…+]BNew Technical Notes†ô°ddrw2:°„†ó°d1drw2eÙġˇˇˇˇˇP°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚ÄE¿†ò
  3042. ({ïDeveloper Support†ô°ddrw2:°„†ó°d`drw2-ÔˇˇˇˇˇˇKÔ- Z  ffZ°d1drw2 ¿˙ÈˇˇˇˇˇˇK°ñ x°ddrw2:°ddrw2:$°d4drw2:0°öˇÙĆò
  3043. 0(UÔ†ô°ddrw2:°„†ó°d1drw2ÔÊ˙ˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:    °öˇ˝Ä†ò
  3044.     +&    ®†ô°ddrw2:°„†ó°d1drw2Â-¯yˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚Ä%†ò
  3045. (Z\    Macintosh†ô°ddrw2:°„†ó†ç°ddrw2D†É
  3046. IR.°dONLNdn<Åfi(õZ.PR 3 - Document Names and the Printing Manager
  3047. °dONLNd/Ä<ès*Printing
  3048. °dONLNd9õ<ßt* Revised by:°dONLNdFõ≈߲(√„
  3049. March 1988°dONLNdQß<≥q(œZ Written by:°dONLNd]ßÑ≥«)H
  3050. Bryan Stearns°dONLNdkßœ≥˛(œÌ    July 1987°dONLNduø<À¡(ÁZROur compatibility testing for LaserShare (Apple’s LaserWriter spooler) has turned °dONLNd«ø¡À˛(Áfl up a number°dONLNd”À<◊ò(ÛZof applications that °dONLNdËÀò◊˛)\Gdo not provide the Printing Manager with a document name; although this°dONLNd0◊<„Y(ˇZBfeature is not required, it is nice for users that share printers. X°dONLNds¸< *%Some printers (usually those °dONLNd긠˛)é=that are shared between many users, like the LaserWriter) can°dONLNdŒ<á(0ZBprovide the names of the users who are printing and the documents °dONLNdá˛(0•that are being printed to°dONLNd*< È(<Z'others interested in using the printer.°dONLNdS,<8*TIf the chosen printer uses a document name, the Printing Manager gets the name from °dONLNdß,8˛(Tthe°dONLNd´8<Dß(`ZJfrontmost window’s title. If there is no front window, or if the window’s °dONLNdı8ßD˛(`≈title is empty, the°dONLNd    D<P(lZ'Printing Manager defaults to “unknown.”°dONLNd1\<hÒ*"This method was chosen because it °dONLNdS\Òh˛)µ5works most transparently to applications; however, it°dONLNdâh<t’(êZwon’t work if your application °dONLNd®h’t˛)ô9doesn’t display windows when printing (for instance, many°dONLNd‚t<Ĉ(úZ(applications that use windows for their °dONLNd
  3051. tˆÄ˛)∫3documents do not open their documents when printing°dONLNd>Ä<å(®Z)in response to a Finder “Print” command).°dONLNdhò<§≥*As a general solution to °dONLNdÅò≥§˛)w?this problem, you can put up a window containing a message like°dONLNd¡ß<≥_(œZ“Press °dONLNd»§_¥j)#°dONLNd…ßj≥) !–. to cancel printing”, and give °dONLNdÍß≥˛)õ3it the document’s title. If the window  is one that°dONLNd¥<¿«(‹Zdoesn’t have a title bar (like ,
  3052. Courier°dONLNd=≥«øˇ)ãdBoxProc°dONLNdE¥ˇ¿m)8), this title will not be °dONLNd_¥m¿˛)ndisplayed. MacApp takes this°dONLNd|¿<ÃH(ËZ8approach. If for some reason you don’t want to put up a °dONLNd¥¿HÃ˛(Ëf%visible window, you can create a tiny°dONLNd⁄Ã<ÿf(ÙZwindow °dONLNd·Ãfÿ˛)*Tand hide it behind the menu bar: for instance, global coordinates of (1,1,2,2). Make°dONLNd6Ÿ<ÂÉ(Zsure you use a °dONLNdEÿɉ¬)G    plainDBox°dONLNdNŸ¬ÂR)?!, so that no title will be drawn °dONLNdoŸR²)ê%(otherwise, in the unlikely case that°dONLNdïÂ<Ò⁄(
  3053. ZTa user is using a Macintosh II with two stacked screens, main screen on the bottom, °dONLNdÈÂ⁄Ò˛(
  3054. ¯    the title°dONLNdÛÒ<˝Ó(Z&might be visible on the upper screen).°dONLNd
  3055. <"*.Since the Printing Manager checks the name at °dONLNdH    "h)Ê
  3056. PrValidate°dONLNdR
  3057. hl)F °dONLNdS
  3058. lû) time, call °dONLNd^    û‰)2
  3059. PrValidate°dONLNdh
  3060. ‰˛)F after°dONLNdo<"Ç(?Z
  3061. PrCloseDoc°dONLNdyÇ#‚)F and before the next °dONLNdé‚"!)`    PrOpenDoc°dONLNdó!#¶)?, if you want unique names.°dONLNd¥/<;fl(WZXA number of applications set the document name in the print record directly. You should °dONLNd /fl;˛(W˝not do°dONLNd;<G§(cZPthis because a) not all printers support this field, and b) none are guaranteed °dONLNdc;§G˛(c¬to support it in the°dONLNdxG<Sõ(oZfuture. (Apple does °dONLNdåGõS˛)_Lnot guarantee that internal fields of the Printing Manager’s data structures°dONLNdŸS<_—({ZXwill remain the same; the Printing Manager is targeted for substantial internal change!)°dONLNd    2k<w¶*Further Reference: ñXñ°dONLNd    ExNÑR+
  3062. •°dONLNd    Gx`Ñ«)The Printing Manager°dONLNd    \ÑNêR(¨l•°dONLNd    ^Ñ`ê©)?Technical Note M.IM.DevIndPrinting— Device-Independent Printing ¡X¡
  3063. (÷Z.PR 3 - Document Names and the Printing Manager(÷1) of 1(ÏZM.PR.DocumentNamesˇ°¿Ù%%DSIDICT:_cv
  3064. currentdict /bu known {bu}if
  3065. userdict /_cv known not{userdict /_cv 30 dict put}if
  3066. _cv begin
  3067. /bdf{bind def}bind def
  3068. currentscreen/cs exch def/ca exch def/cf exch def
  3069. /setcmykcolor where{/setcmykcolor get /cvcmyk exch def}{/cvcmyk{1 sub 4 1 roll 3{3 index add neg dup 0 lt{pop 0}if 3 1 roll}repeat setrgbcolor pop}bdf }ifelse
  3070. /ss{//cf //ca //cs setscreen}bdf
  3071. /stg{ss setgray}bdf
  3072. /strgb{ss setrgbcolor}bdf
  3073. /stcmyk{ss cvcmyk}bdf
  3074. /min1{dup 0 eq{pop 1}if}bdf
  3075. end
  3076. currentdict /bn known {bn}if
  3077. †ø®◊#ˇ ˇˇˇˇ#◊†Ç 
  3078. /ZÅ#
  3079.     0Ià:µú9"{    ˇˇˇˇˇˇˇˇ#†ƒ°d
  3080. ONLNf˛†å°d1drw2…-·_ġˇˇˇˇˇè°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˙ó@†ò,Times
  3081. .R…R…+]BNew Technical Notes†ô°ddrw2:°„†ó°d1drw2eÙġˇˇˇˇˇP°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚ÄE¿†ò
  3082. ({ïDeveloper Support†ô°ddrw2:°„†ó°d`drw2-ÔˇˇˇˇˇˇKÔ- Z  ffZ°d1drw2 ¿˙ÈˇˇˇˇˇˇK°ñ x°ddrw2:°ddrw2:$°d4drw2:0°öˇÙĆò
  3083. 0(UÔ†ô°ddrw2:°„†ó°d1drw2ÔÊ˙ˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:    °öˇ˝Ä†ò
  3084.     +&    ®†ô°ddrw2:°„†ó°d1drw2Â-¯yˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚Ä%†ò
  3085. (Z\    Macintosh†ô°ddrw2:°„†ó†ç°ddrw2D†É
  3086. IR.°dONLNdn<Å≠(õZ*PR 4 - LaserWriter Optimization Techniques
  3087. °dONLNd+Ä<ès*Printing
  3088. °dONLNd5õ<ßt* Revised by:°dONLNdAõÑß)HPete “Luke” Alexander°dONLNdWõæß˛(√‹ October 1990°dONLNddß<≥q(œZ Written by:°dONLNdpßÑ≥–)HGinger Jernigan°dONLNdÄß∏≥˛(œ÷
  3089. February 1986°dONLNdéø<À˜(ÁZ]This Technical Note discusses techniques for optimizing code for printing on the LaserWriter.°dONLNdÏÀ<◊ô* Changes since °dONLNd˙Àô◊Â)] March 1988:°dONLNdÀÂ◊˛)L0  Updated the “Printable Paper Area” and “Memory°dONLNd6◊<„0(ˇZ5Considerations” sections as well as the printer IDs, °dONLNdk◊0„˛)Ù(moved the error messages from the end of°dONLNdî„<Ô£( Zthe Note to Technical °dONLNd™„£Ô˙)g@Note #161, A Printing Loop That Cares…, and removed the “Spool-A°dONLNdÍ„˙Ô˛( -°dONLNdÎÔ<˚ (Z-Page/Print-A-Page” section because Technical °dONLNdÔ ˚˙)‰)Note #125, Effect of Spool-A-Page/Print-A°dONLNdAÔ˙˚˛)⁄-°dONLNdB˚<b(#Z>Page on Shared Printers, already thoroughly covers this topic. 2X2
  3090. °dONLNdÅ,<;è*4 Introduction
  3091. °dONLNdéG<S—*Although the Printing Manager °dONLNd¨G—S˛)ï?was originally designed to allow application code to be printer°dONLNdÏS<_\({Z9independent, there are some things about the LaserWriter °dONLNd%S\_˛({zthat, in some cases, have to be°dONLNdE_<kô(áZDaddressed in a printer dependent way.  This Note describes what the °dONLNdâ_ôk˛(á∑LaserWriter can and°dONLNdùk<w^(ìZcannot °dONLNd§k^w˛)"Tdo, memory considerations, speed considerations, as well as other things you need to°dONLNd˘w<É¿(üZRwatch out for if you want to make your printing more efficient on the LaserWriter.
  3092. °dONLNdLõ<™é*'/How To Determine The Currently Selected Printer
  3093. °dONLNd|∑<√i*    With the °dONLNdÖ∑i√?)-)addition of new picture comments and the ,
  3094. Courier°dONLNdÆ∂?¬~)÷    PrGeneral°dONLNd∑∑~√˛)? procedure, an application°dONLNd“√<œb(ÎZ9should never need to know the type of device to which it °dONLNd √bœ˛(ÎÄis connected.  However, some°dONLNd(œ<€|(˜ZFdevelopers feel their application should be able to take advantage of °dONLNdnœ|€˛(˜öall of the features provided°dONLNdã€<Á%(Z3by a particular device, not just those provided by °dONLNdæ€%Á˛)È,the Printing Manager, and in doing so, these°dONLNdÎÁ<Ûn(Z<developers produce device-dependent applications, which can °dONLNd'ÁnÛ˛(åproduce unpredictable results°dONLNdEÛ<ˇ
  3095. (Z,third-party and new Apple printing devices. °dONLNdqÛ
  3096. ˇ˛)—0 For this reason, Apple strongly recommends that°dONLNd¢ˇ< ~('ZCyou use only the features provided by the Printing Manager, and do °dONLNd¡~ ˛('únot try to use unsupported°dONLNd <Ü(3Zdevice features.°dONLNd#</∫*PEven though there is no supported method for determining a device’s type, there °dONLNda#∫/˛(Kÿ
  3097. is one method°dONLNdo/<;z(WZ
  3098. described in °dONLNd|/z;∂)>
  3099. the original °dONLNdâ/∂;)<Inside Macintosh °dONLNdö/;˛)X0that still works for ImageWriter and LaserWriter°dONLNdÀ;<G“(cZ!printer drivers.  This method is °dONLNdÏ;“G‰)ñnot°dONLNdÔ;‰G)  supported, °dONLNd˚;G˛)90meaning that at some point in the future it will°dONLNd,G<S!(oZ0no longer work.  If you use this method in your °dONLNd\G!S˛)Â/application, it is up to you to weigh the value°dONLNdåS<_#({Z4of the feature against the compatibility risk.  The °dONLNd¿S#_˛)Á+following method works for all ImageWriter,°dONLNdÏ_<kz(áZ ImageWriter °dONLNd¯_zk0)>'II, and LaserWriter (original, Plus, II
  3100. °dONLNd    _0k=)∂NT
  3101. °dONLNd    !_=kM)
  3102. , II
  3103. °dONLNd    %_Mka)NTX
  3104. °dONLNd    (_ak˛)!) drivers.  Since all new devices°dONLNd    Jk<wß(ìZIreleased from Apple and third-party developers have their own unique ID, °dONLNd    ìkßw˛(ì≈it is up to you to°dONLNd    ¶w<ÉÜ(üZFdecide what to do with an ID that your application does not recognize. ¡X¡
  3105. *7*PR 4 - LaserWriter Optimization Techniques(÷1) of 6(ÏZM.PR.LaserWriterOptˇ°¿Ù%%DSIDICT:_cv
  3106. currentdict /bu known {bu}if
  3107. userdict /_cv known not{userdict /_cv 30 dict put}if
  3108. _cv begin
  3109. /bdf{bind def}bind def
  3110. currentscreen/cs exch def/ca exch def/cf exch def
  3111. /setcmykcolor where{/setcmykcolor get /cvcmyk exch def}{/cvcmyk{1 sub 4 1 roll 3{3 index add neg dup 0 lt{pop 0}if 3 1 roll}repeat setrgbcolor pop}bdf }ifelse
  3112. /ss{//cf //ca //cs setscreen}bdf
  3113. /stg{ss setgray}bdf
  3114. /strgb{ss setrgbcolor}bdf
  3115. /stcmyk{ss cvcmyk}bdf
  3116. /min1{dup 0 eq{pop 1}if}bdf
  3117. end
  3118. currentdict /bn known {bn}if
  3119. †øö◊#ˇ ˇˇˇˇ#◊ 
  3120. IR,Times
  3121. .+6-Macintosh Technical Notes /4/˘
  3122. °dONLNd*j*If you are using °dONLNdj*h)R6the high-level Printing Manager interface, first call ,
  3123. Courier°dONLNdGh)Æ)˛
  3124. PrValidate°dONLNdQÆ*⁄)F to make°dONLNdZ+7W(S6Fsure you have the correct print record.  Look at the high byte of the °dONLNd†*W6s(Suwdev°dONLNd§+s7û)     word in °dONLNd≠+û7∞)+the °dONLNd±*∞6⁄)TPrStl°dONLNd∏7Cƒ(_6Wsubrecord of the print record.  Note that if you have your own driver and want to have °dONLNd7ƒC⁄(_‚your°dONLNdCO4(k69own number, please let DTS know, and DTS can register it.°dONLNdN[g‡*-Following is the current list of printer IDs:°dONLNd|sÑ´+lPrinter°dONLNdÑs\|)ÿwDev û†ûü°dONLNdâÄÑå(®¢ImageWriter I, ImageWriter II°dONLNdßÄiåo)Â1°dONLNd©åÑò8(¥¢%LaserWriter, LaserWriter Plus, Laser-°dONLNdœòѧ≠*     Writer II
  3125. °dONLNdÿò≠§∫))NT
  3126. °dONLNd⁄ò∫§)
  3127. , LaserWriter II
  3128. °dONLNdÍò§)JNTX
  3129. °dONLNdÌò§0), and°dONLNdÛ§Ñ∞Î(âPersonal LaserWriter 
  3130. °dONLNd§Î∞¯)gNT
  3131. °dONLNd §i∞o)~3°dONLNd
  3132. ∞Ѻ«(ÿ¢LaserWriter II
  3133. °dONLNd∞«º‘)CSC
  3134. °dONLNd∞‘ºB)
  3135. , Personal LaserWriter 
  3136. °dONLNd4∞BºO)nSC
  3137. °dONLNd7∞iºo)'4°dONLNd9ºÑ»—(‰¢ImageWriter LQ°dONLNdHºi»o)Â5 Á†Áü°dONLNdJ·Ì∫(    6YIf you are using the low-level Printing Manager interface, there is no dependable way of °dONLNd£·∫Ì⁄(    ÿgetting°dONLNd´Ì˘…(6"the wDev information.  You should °dONLNdÕÌ…˘€)±not°dONLNd–Ì€˘fl) °dONLNd—Ìfl˘⁄)1attempt to determine the device ID when using the°dONLNd˘»(!6%low-level Printing Manager interface.
  3138. °dONLNd),#*'$Using QuickDraw With the LaserWriter
  3139. °dONLNdN8D«*#When you print to the LaserWriter, °dONLNdq8«D⁄)Ø7all of the QuickDraw calls you make are translated (via°dONLNd©EQŸ(m6&QuickDraw bottlenecks) into PostScript
  3140.     °dONLNdœCŸN‡(j˜®
  3141. °dONLNd–E‡Qû+$, which is in the LaserWriter ROM.  °dONLNdÙEûQ⁄)æ Most of the°dONLNdQ]M(y6 operations °dONLNd QM]⁄)5Oavailable in QuickDraw are available in PostScript, with a few exceptions.  The°dONLNd[]i(Ö62LaserWriter driver does not support the following:°dONLNdév*Ç.+•°dONLNdêu7ÅL)
  3142. XOR°dONLNdìvLÇc) and °dONLNdòucÅç)NotXOR°dONLNdûvçÇ⁄)* transfer modes.°dONLNdØÉ*è.(´H•°dONLNd±É7èw)
  3143.  
  3144. The grafverb °dONLNdæÇwé°)@invert°dONLNdƒɰè•)*.°dONLNdΔê*ú.(∏H•°dONLNd»è7õ})
  3145. _SetOrigin°dONLNd“ê}úû)F calls °dONLNdŸêûú√)!within °dONLNd‡è√õ    )%
  3146. PrOpenPage°dONLNdÍê    ú()F and °dONLNdÔè(õu) PrClosePage°dONLNd˙êuú∂)M  calls.  Use°dONLNdú7®Ñ(≈U _OffsetRect°dONLNdùÑ©¶)MB instead.  (This is fixed in version 3.0 and later of the driver.)°dONLNdU©*µ.(—H•°dONLNdW©7µ)
  3147. 'Regions are ignored.  You can simulate °dONLNd~©µ∂)À"regions using polygons or bitmaps.°dONLNd¢µ7¡Ä(›U@Refer to Technical Note #41, Drawing Into An Off-Screen Bitmap, °dONLNd‚µÄ¡∂(›û
  3148. for how to°dONLNdÌ¡7Õ±(ÈUcreate off-screen bitmaps.°dONLNdÕ*Ÿ.(ıH•°dONLNd
  3149. Õ7Ÿ)
  3150. -Clip regions should be limited to rectangles.°dONLNd8Ÿ*Â.(H•°dONLNd:Ÿ7ÂU)
  3151. There °dONLNd@ŸUÂ∂)Jis a small difference in character widths between screen fonts and printer°dONLNdãÂ7Ò:(
  3152. U9fonts.  Only the end points of text strings are the same.
  3153. °dONLNd≈    ;(46'What You See Is Not Always What You Get
  3154. °dONLNdÌ$0î*JUnfortunately, what you see on the screen is not always what you get.  If °dONLNd7$î0⁄(L≤
  3155. you are using°dONLNdE0<E(X6    standard °dONLNdN0E<⁄)-Sgraphic objects, like rectangles, circles, etc., the object is the same size on the°dONLNd¢<Hπ(d6$LaserWriter as it is on the screen. °dONLNdΔ<πH⁄)°; There are, however, two types of objects where this is not°dONLNdHTó(p6the case:  text and bitmaps.°dONLNd`l-*The °dONLNd#`-l⁄)Yearlier noted difference between the widths of characters on the screen and the widths of°dONLNd}lx(î66characters on the printer is due to the difference in °dONLNd≥lx⁄(î8%resolution.  However, to maintain the°dONLNdŸxÑö(†6integrity of line breaks, the °dONLNd˜xöÑ⁄)ÇAdriver changes the word and character spacing to maintain the end°dONLNd    9Ñê–(¨6apoints of the lines as specified.  What this all means is that you cannot count on the positions °dONLNd    öÑ–ê⁄(¨Óor ¡4¡˘
  3156. (÷62) of 6(÷E*PR 4 - LaserWriter Optimization Techniques+ZM.PR.LaserWriterOptˇΔ◊#ˇ ˇˇˇˇ#◊ 
  3157. IR,Times
  3158. .+Z-Developer Support Center(-Ê October 1990 /X/
  3159. °dONLNd<)@(EZ8the widths of printed characters being exactly the same °dONLNd8@)˛(E^'as they are on the screen.  This is why°dONLNd`*<6Æ(RZin the original MacDraw
  3160.     °dONLNdw(Æ3µ(Oî
  3161. °dONLNdx*µ6Ù+G, for example, if one carefully places text and a rectangle and prints °dONLNdø*Ù6˛(Rit,°dONLNd√6<BN(^Zthe °dONLNd«6NB˛)Utext sometimes extends beyond the bounds of the rectangle on the printed page.  If an°dONLNdB<Nå(jZGapplication does its own line layout (i.e., positions the words on the °dONLNddBåN˛(j™line itself), then it may°dONLNd~N<ZL(vZ8want to disable the LaserWriter’s line layout routines. °dONLNd∂NLZ˛(vj# To disable these routines, use the,
  3162. Courier°dONLNd⁄Z<fó(ÉZ
  3163. LineLayoutOff°dONLNdÁ[óg√)[     picture °dONLNd[√g˛),9comment described in the LaserWriter Reference Manual and°dONLNd*g<só(èZDTechnical Note #91, Optimizing for the LaserWriter—Picture Comments.°dONLNdo<ã/*5The sole exception to this rule is if an application °dONLNd§/ã˛)Û&is running on 128K ROMs or later.  The°dONLNdÀã<ó‚(≥ZW128K ROM Font Manager supports the specification of fractional pixel widths for screen °dONLNd"ã‚ó˛(≥fonts,°dONLNd)ó<£Ä(øZincreasing the °dONLNd8óÄ£˛)DRscreen to printer accuracy.  This fractional width feature is disabled by default.°dONLNdå§<∞Á(ÃZ&To enable it, an application  can use °dONLNd≤£ÁØP)´_SetFractEnable°dONLNd¡§P∞ë)i, after calling °dONLNd—£ëØ◊)A
  3164. _InitFonts°dONLNd€§◊∞€)F.°dONLNd›º<»è(‰ZApplications can °dONLNdÓºè»˛)SNuse picture comments to left-, right-, or center-justify text.  Only the left,°dONLNd=»<‘*(Z2right, or center end points are accurate.  If the °dONLNdo»*‘˛)Ó,text is fully justified, both end points are°dONLNdú‘<‡ú(¸Zaccurate.  Technical °dONLNd±‘ú‡˛)`DNote #91, Optimizing for the LaserWriter—Picture Comments, discusses°dONLNdˆ‡<ÏÆ(Zthese picture comments.
  3165. °dONLNd<⁄*'Memory Considerations
  3166. °dONLNd$<+Ô*&To print to the LaserWriter, you need °dONLNdJÔ+˛)≥5to make sure that you have enough memory available to°dONLNdÄ+<7Ï(SZ_load the driver’s code.  The best way to do this is to have all the code you need for printing °dONLNdfl+Ï7˛(S
  3167. in a°dONLNd‰7<C6(_Z3separate segment and unload everything else.  When °dONLNd76C˛)˙)you print to the LaserWriter you are only°dONLNdAC<OL(kZ<able to print in Draft mode.  You are not able to spool (as °dONLNd}CLO˛(kj$the ImageWriter does in the standard°dONLNd¢O<[»(wZor high-quality settings), and °dONLNd¡O»[˛)åAyour print code, data, and the driver code have to be resident in°dONLNd[<gg(ÉZmemory.°dONLNd s<Ÿ*QIn terms of memory requirements, there is not any magic number that always works °dONLNd\sŸ˛(õ˜with all°dONLNde<ã≤(ßZSprinter drivers (including third-party printer drivers) that are available for the °dONLNd∏≤ã˛(ß–Macintosh.  To°dONLNd«ã<ó2(≥Z2make sure there is enough memory available during °dONLNd˘ã2ó˛)ˆ)print time, you should make your printing°dONLNd#ò<§Ω(¿ZPcode a separate segment and swap out all unwanted code and data before you call °dONLNdsóΩ£Ó(¿€_PrOpen°dONLNdzòÓ§Ú)1.
  3168. °dONLNd|º<À…(ÁZPrintable Paper Area
  3169. °dONLNdë◊<„|*BOn the LaserWriter there is a 0.45-inch border that surrounds the °dONLNd”◊|„˛(ˇöprintable area of the paper°dONLNdÔ„<Ô»( ZV(this is assuming an 8.5” x 11” paper).  If you select the “Larger Print Area” option °dONLNd    E„»Ô˛( Ê in the Page°dONLNd    QÔ<˚§(ZSetup dialog box, the °dONLNd    gÔ§˚˛)hIborder changes to 0.25 of an inch.  This printable area is different than°dONLNd    ±˚<ï(#ZLthe available print area of the ImageWriter.  An application cannot print a °dONLNd    ˝˚ï˛(#≥larger area because of°dONLNd
  3170. <{(/Z the memory °dONLNd
  3171. {˛)?HPostScript needs to image a page.  PostScript takes the amount of memory°dONLNd
  3172. h<Î(;Z%available in the printer and centers °dONLNd
  3173. çβ)Ø3it on the paper, and there is not enough RAM in the°dONLNd
  3174. ¡<+(GZ.LaserWriter to image an entire sheet of paper.
  3175. °dONLNd
  3176. C<RÅ*'
  3177. Page Sizes
  3178. °dONLNd
  3179. ˚^<j√*OMany developers have expressed a desire to support page sizes other than those °dONLNd J^√j˛(Ü· provided by°dONLNd Vj<v‘(íZ!the Apple printer drivers.  Even °dONLNd wj‘v˛)ò<though some devices can physically support other page sizes,°dONLNd ¥v<Çã(ûZthere is no way °dONLNd ƒvãDz)OMfor an application to tell the driver to use this size.  With the ImageWriter°dONLNd Ç<éx(™ZHdriver, it is possible to modify certain fields in the print record and °dONLNd ZÇxé˛(™ñexpand the printable area of ¡X¡
  3180. (÷Z*PR 4 - LaserWriter Optimization Techniques(÷3) of 6(ÏZM.PR.LaserWriterOptˇ◊#ˇ ˇˇˇˇ#◊ 
  3181. IR,Times
  3182. .+6-Macintosh Technical Notes /4/˘
  3183. °dONLNd)ï*Mthe page.  However, each of the Apple drivers implements the page sizes in a °dONLNdMï)⁄(E≥different way.°dONLNd])5ñ(Q6No one method works for °dONLNdu)ñ5⁄)~Dall drivers.  Because of this difference, it is strongly recommended°dONLNd∫5AN(]6Cthat applications do not attempt to change the page sizes provided °dONLNd˝5NA⁄(]lin the “Style” dialog box.  If°dONLNdAMî(i6your application currently °dONLNd7AîM⁄)|Dsupports page sizes other than those provided by the printer driver,°dONLNd|MYΔ(u6^you are taking a serious compatibility risk with future Apple and third-party printer drivers.
  3184. °dONLNd€qÄ•*'Speed Considerations
  3185. °dONLNdåò˛*3Although the LaserWriter is relatively fast, there °dONLNd#å˛ò⁄)Ê-are some techniques an application can use to°dONLNdQò§π(¿6ensure its maximum performance.°dONLNdq±*Ω.+•°dONLNds±7ΩQ)
  3186. Try °dONLNdw±QΩl)0to avoid using the QuickDraw Erase calls (e.g., ,
  3187. Courier°dONLNdß∞lº≤(Ÿä
  3188. _EraseRect°dONLNd±±≤Ω∂)F,°dONLNd≥Ω7…}(ÊU
  3189. _EraseOval°dONLNdΩæ} ≠)F
  3190. , etc.).  It °dONLNd æ≠ ∂)08takes a lot of time to handle the erase function because°dONLNd 7÷D(ÚU;every bit (90,000 bits per square inch) has to be cleared. °dONLNd> D÷∂(Úb Erasing is unnecessary°dONLNdV÷7‚Ä(˛UEbecause the paper does not need to be erased the way the screen does.°dONLNdúÓ*˙.(H•°dONLNdûÓ7˙/)
  3191. 7Printing patterns takes time, since the bitmap for the °dONLNd’Ó/˙∂)¯pattern has to be built.  The°dONLNdÛ˚7_(#U    patterns °dONLNd¸˙_Ç)(black°dONLNd˚Çâ)#, °dONLNd˙â¨)white°dONLNd˚¨®)#7, and all the gray patterns have been optimized to use °dONLNd?˚®∂)¸the°dONLNdC7û(/UNPostScript gray scales.  If you use a different pattern it works, but it just °dONLNdëû∂(/ºtakes°dONLNdó7i(;UDlonger than usual.  In addition, the patterns in driver version 3.0 °dONLNd€i∂(;áare rotated; they°dONLNdÌ7+√(GUare not rotated in version 1.0.°dONLNd
  3192. 7*C.(_H•°dONLNd77C˜)
  3193. )Try to avoid frequently changing fonts.  °dONLNd87˜C∂)¿)PostScript has to build each character it°dONLNdbC7O¨(kUNneeds either by using the drawing commands for the built-in LaserWriter fonts °dONLNd∞C¨O∂(k or°dONLNd≥O7[è(wUDby resizing bitmaps downloaded from screen fonts on the Macintosh.  °dONLNd˜Oè[∂(w≠As each°dONLNdˇ[7gq(ÉU
  3194. character is °dONLNd [qg∂):Ebuilt, it is cached (if there’s room), so if that character is needed°dONLNdRg7sá(èUEagain PostScript gets if from the cache.  When the font changes, the °dONLNdógás∂(è•
  3195. characters°dONLNd¢s7r(õUEhave to be built from scratch in the new font, which takes time.  If °dONLNdÁsr∂(õêthe font is not°dONLNd˜7ãú(ßUin the LaserWriter, it °dONLNdúã∂)e:takes time to download it from the Macintosh.  If the user°dONLNdIã7óΔ(≥Uhas the option of choosing °dONLNddãΔó∂)è.fonts, you have no control over this variable;°dONLNdìó7£`(øU?however, if you  control which fonts to use, keep this in mind.°dONLNd”∞*º.(ÿH•°dONLNd’∞7ºx)
  3196. Avoid using °dONLNd·Øxª∞)A_TextBox°dONLNdÈ∞∞º)8.  It makes calls to °dONLNd˛Øª[)e
  3197. _EraseRect°dONLNd∞[ºÜ)F, which °dONLNd∞ܺ∂)+    slows the°dONLNdº7»^(‰UAprinter, for every line of text it draws.  You might want to use °dONLNd[º^»∂(‰|a different method°dONLNdn…7’E(ÒUof °dONLNdq…E’±)displaying text (e.g., °dONLNdà»±‘˛)l _DrawString°dONLNdì…˛’)M or °dONLNdó»‘Q)    _DrawText°dONLNd†…Q’∂)?) or write your own°dONLNd¥÷7‚p(˛U version of °dONLNdø’p·®)9_TextBox°dONLNd«÷®‚≤)8. °dONLNd…÷≤‚z)
  3198. ( If an application is currently calling °dONLNdÒ’z·≤)»_TextBox°dONLNd˘÷≤‚∂)8,°dONLNd˚‚7Óm(
  3199. U@changing to another method of displaying text can improve speed °dONLNd    ;‚mÓ∂(
  3200. ãon the order of°dONLNd    KÓ7˙m(U five to one.°dONLNd    X*.(.H•°dONLNd    Z7p)
  3201. Because of °dONLNd    ep∂)9Cthe way rectangle intersections are determined, if your clip region°dONLNd    ©7ï(;Ufalls outside of the °dONLNd    æï∏)^rPage°dONLNd    √∏)# rectangle, you °dONLNd    ”∂)L$slow down the printer substantially.°dONLNd    ˘ 7,%(HU3By making sure your clip region is entirely within °dONLNd
  3202. , %,7)Óthe °dONLNd
  3203. 07+Z)rPage°dONLNd
  3204. 5 Z,∂)# rectangle, you can°dONLNd
  3205. I,78:(TU5get a speed improvement of approximately four to one.°dONLNd
  3206. D*P.(lH•°dONLNd
  3207. ÅD7PH)
  3208. Do °dONLNd
  3209. ÑDHP∂)Jnot use spool-a-page/print-a-page as some applications do when printing on°dONLNd
  3210. œP7\ó(xUCthe ImageWriter.  It slows things down considerably because of all °dONLNd Pó\∂(xµof the°dONLNd \7hì(ÑUpreparation that has,     Helvetica°dONLNd -[ìiñ)\ °dONLNd .\ñh¢)to °dONLNd 1\¢h∂) 9be done when a job is initiated.  Refer to Technical Note°dONLNd kh7té(êU#125, Effect of °dONLNd {hét∂)W6Spool-A-Page/Print-A-Page on Shared Printers, for more°dONLNd ≤t7Är(úU information. ¡4¡˘
  3211. (÷64) of 6(÷E*PR 4 - LaserWriter Optimization Techniques+ZM.PR.LaserWriterOptˇ¸◊#ˇ ˇˇˇˇ#◊ 
  3212. IR,Times
  3213. .+Z-Developer Support Center(-Ê October 1990 /X/
  3214. °dONLNdN*R(Fl•°dONLNd[*{)
  3215. Using ,
  3216. Courier°dONLNd{)∫)     _DrawChar°dONLNd∫*.)? to place every character °dONLNd+.*⁄)t%to print can take a lot of time.  One°dONLNdQ*[6(Ry%reason, of course, is because it has °dONLNdv*6⁄)∂'to go through the bottlenecks for every°dONLNdû6[Bπ(^yPcharacter that is drawn.  The other is that the printer driver does its best to °dONLNdÓ6πB⁄(^◊do line°dONLNdˆB[N¥(jyGlayout, making the character spacing just right.  If you are trying to °dONLNd=B¥N⁄(j“position°dONLNdFN[Zí(vyFcharacters and the driver is trying to position characters too, there °dONLNdåNíZ⁄(v∞is conflict, and°dONLNdùZ[fÃ(ÇyPprinting takes much longer than necessary.  In version 3.0 of the driver, there °dONLNdÌZÃf⁄(ÇÍare°dONLNdÒf[r(éy(picture comments that turn off the line °dONLNdfr⁄)Ω(layout optimization, alleviating some of°dONLNdBr[~ú(öy
  3217. the problem. °dONLNdOrú~Œ)A< Refer to Technical Note #91, Optimizing for the LaserWriter°dONLNdãrŒ~⁄(öÏ—°dONLNdå~[ä (¶y'Picture Comments, for more information.
  3218. °dONLNd¥¢<±˛(ÕZClipping Within Text Strings
  3219. °dONLNd—Ω<…π*When clipping characters °dONLNdÍΩπ…˛)}Cout of a string, make sure that the clipping rectangle or region is°dONLNd.…<’…(ÒZWgreater than the bounding box of the text you want to clip.  The reason is that if you °dONLNdÖ……’˛(ÒÁ clip part of°dONLNdí’<·l(˝ZAa character (e.g., a descender), the clipped character has to be °dONLNd”’l·˛(˝ärebuilt, which takes time.  In°dONLNdÚ·<Ìú(    ZLaddition, because of the difference between screen fonts and printer fonts, °dONLNd>·úÌ˛(    ∫chances are that you°dONLNdSÌ<˘o(ZCcannot accurately clip the right characters unless you are running °dONLNdñÌo˘˛(çon the 128K ROMs and have°dONLNd∞˘<–(!Z fractional pixel widths enabled.
  3220. °dONLNd—<,#*'!When to Validate the Print Record
  3221. °dONLNdÛ9<EÑ*To validate the °dONLNd9ÑEÿ)Hprint record, call °dONLNd8ÿD)T
  3222. PrValidate°dONLNd 9E˛)F0.  You need validation to check to see if all of°dONLNdQE<Qj(mZBthe fields are accurate according to the current printer selected °dONLNdìEjQ˛(màand the current version of the°dONLNd≤R<^æ(zZdriver.  You should call °dONLNdÀQæ])Ç
  3223. PrValidate°dONLNd’R^≤)F when you have allocated a new °dONLNdÙR≤^˛)Æprint record or°dONLNd_<k”(áZRwhenever you need to access information from the print record (i.e., when you get °dONLNdV^”jˆ(áÒrPage°dONLNd[_ˆk˛)#).°dONLNd_l<xz(îZ
  3224. The routines °dONLNdlkzw«)> PrStlDialog°dONLNdwl«xfi)M and °dONLNd|kfiw+) PrJobDialog°dONLNdál+xA)M call °dONLNdçkAwá)
  3225. PrValidate°dONLNdóláxæ)F  when they °dONLNd¢læx˛)7are called, so°dONLNd±x<ÑC(†Z9you do not have to worry about it if you use these calls.
  3226. °dONLNdÎú<´Ì*'Empty QuickDraw Objects
  3227. °dONLNd∑<√¬*QuickDraw objects that are °dONLNd∑¬√˛)Ü@empty (i.e., they have no pixels in them) and are filled but not°dONLNd_√<œd(ÎZframed, °dONLNdg√dœ˛)(Qdo not print on the ImageWriter and do not show up on the screen; however, on the°dONLNdπœ<€(˜Z/LaserWriter they are real objects and do print. ¡X¡
  3228. *fl*PR 4 - LaserWriter Optimization Techniques(÷5) of 6(ÏZM.PR.LaserWriterOptˇÆ◊#ˇ ˇˇˇˇ#◊ 
  3229. IR,Times
  3230. .+6-Macintosh Technical Notes /4/˘
  3231. °dONLNd)Ç*Further Reference: H4H˘°dONLNd**6.+
  3232. •°dONLNd*<6ç)Inside Macintosh°dONLNd%*ç6˝)Q, Volume I, QuickDraw°dONLNd;6*B.(^H•°dONLNd=6<Bç)Inside Macintosh°dONLNdM6çB2)Q!, Volume II, The Printing Manager°dONLNdoB*N.(jH•°dONLNdqB<NÃ)LaserWriter Reference Manual°dONLNdéN*Z.(vH•°dONLNdêN<Z)$Technical Note M.IM.OffscreenBitMap—°dONLNd∑Z`f+$ " Drawing Into An Off-Screen Bitmap°dONLNd⁄f*r.(éH•°dONLNd‹f<r˙)"Technical Note M.IM.PictComments —°dONLNdr`~W+$ 0 Optimizing for the LaserWriter—Picture Comments°dONLNd2~*ä.(¶H•°dONLNd4~<ä⁄)Technical Note M.IM.Spooler —°dONLNdTä`ñn+$ 7 Effect of Spool-A-Page/Print-A-Page on Shared Printers°dONLNdåñ*¢.(æH•°dONLNdéñ<¢Â)Technical Note M.IM.PrintLoop —°dONLNd∞¢`ÆÚ+$  A Printing Loop That Cares…°dONLNdÕÆ*∫.(÷H•°dONLNdœÆ<∫d):PostScript Language Reference, Adobe Systems, Incorporated°dONLNd
  3233. ∫*Δ.(‚H•°dONLNd ∫<Δ£)FPostScript Language Tutorial and Cookbook, Adobe Systems, Incorporated°dONLNdS“fi((˙68MacDraw is a registered trademark of Claris Corporation.°dONLNdåfiÍ`* DPostScript is a registered trademark of Adobe Systems, Incorporated. ¡4¡˘
  3234. (÷66) of 6(÷E*PR 4 - LaserWriter Optimization Techniques+ZM.PR.LaserWriterOptˇ†◊#ˇ ˇˇˇˇ#◊†Ç 
  3235. /ZÅ#
  3236.     0Ià:µú9"{    ˇˇˇˇˇˇˇˇ#†ƒ°d
  3237. ONLNf˛†å°d1drw2…-·_ġˇˇˇˇˇè°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˙ó@†ò,Times
  3238. .R…R…+]BNew Technical Notes†ô°ddrw2:°„†ó°d1drw2eÙġˇˇˇˇˇP°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚ÄE¿†ò
  3239. ({ïDeveloper Support†ô°ddrw2:°„†ó°d`drw2-ÔˇˇˇˇˇˇKÔ- Z  ffZ°d1drw2 ¿˙ÈˇˇˇˇˇˇK°ñ x°ddrw2:°ddrw2:$°d4drw2:0°öˇÙĆò
  3240. 0(UÔ†ô°ddrw2:°„†ó°d1drw2ÔÊ˙ˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:    °öˇ˝Ä†ò
  3241.     +&    ®†ô°ddrw2:°„†ó°d1drw2Â-¯yˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚Ä%†ò
  3242. (Z\    Macintosh†ô°ddrw2:°„†ó†ç°ddrw2D†É
  3243. IR.°dONLNdn<ÅB(õZPR 5 - LaserWriter ROMs Bugs
  3244. °dONLNdÄ<ès*Printing
  3245. °dONLNd'õ<ßt* Revised by:°dONLNd3õÑß–)HGinger Jernigan°dONLNdCõœß˛(√Ì    July 1987°dONLNdMß<≥g(œZUpdated:°dONLNdWß≈≥˛(œ„
  3246. March 1988°dONLNdb≥<øq(€Z Written by:°dONLNdn≥Ñø–)HGinger Jernigan°dONLNd~≥Œø˛(€ÏMay 1987°dONLNdáÀ<◊!(ÛZ/These are LaserWriter bugs that your users may °dONLNd∂À!◊µ)Âencounter when printing from °dONLNd”Àµ◊…)îany°dONLNd÷À…◊˛)
  3247.  Macintosh°dONLNd·◊<„Å(ˇZDapplication. These are for your information; you cannot code around °dONLNd%◊Å„˛(ˇüthem. The bugs described°dONLNd>„<Ô%( Z/here occur in the 1.0 and 2.0 LaserWriter ROMs. X°dONLNdn<}*%
  3248. To determine °dONLNd{}˛)AOwhich ROMs their LaserWriter contains, users can look at the test page that the°dONLNdÀ< $(<Z4LaserWriter prints at start-up time. In addition to °dONLNdˇ$ ˛)Ë.other information (detailed in the LaserWriter°dONLNd. <,(HZ)user’s manual), the ROM version is shown °dONLNdW ,˛)›-at the bottom of the line graph. The original°dONLNdÖ,<8-(TZ,LaserWriter contained version 1.0 ROMs. The °dONLNd±,-8˛)Ò(currently shipping LaserWriter and those°dONLNd⁄8<D\(`Z:upgraded to the LaserWriter Plus contain version 2.0 ROMs.°dONLNdP<\**These are some of the problems we know of:°dONLNd@h<tF*1.°dONLNdChNt•)NIf the level of paper in the paper tray is getting low, and the user prints a °dONLNdëh•t˛(ê√document that will°dONLNd§t<Ä(úZ-cause the tray to become empty, a PostScript °dONLNd—tIJ)÷0error may occur. This problem exists in both the°dONLNdÄ<å¸(®Z&1.0 and 2.0 LaserWriter ROMs and will °dONLNd(ĸå)¿not°dONLNd+Äå≤)" be fixed in the next ROM version.°dONLNdNò<§F(¿Z2.°dONLNdQòN§)(If a user prints more than 15 copies of °dONLNdyò§˛)∑1a document, a timeout condition may occur causing°dONLNd´§<∞Ñ(ÃZthe print job to °dONLNdº§Ñ∞˛)HLabort. With LaserShare, this problem can occur with as few as 9 copies. This°dONLNd    ∞<º∂(ÿZSproblem is a result of the LaserWriter turning AppleTalk off while it is printing. °dONLNd\∞∂º˛(ÿ‘It doesn’t send°dONLNdlº<»•(‰Zout any packets to tell °dONLNdѺ•»˛)iLthe world it’s still alive while it is printing, so the connection times out°dONLNd—»<‘;(Z7after about 2 minutes. This problem exists in both the °dONLNd»;‘˛)ˇ%1.0 and 2.0 LaserWriter ROMs and will°dONLNd.‘<‡N(¸Znot°dONLNd1‘N‡Ú)" be fixed in the next ROM version.°dONLNdTÏ<¯F(Z3.°dONLNdWÏN¯¡)DWhen printing a document that contains more than 10 patterns, users °dONLNdõÏ¡¯˛(fl may receive°dONLNd߯<f( Z@intermittent PostScript errors. This usually occurs when trying °dONLNdÁ¯f·( Ñto print a lot of patterns, °dONLNd¯·ı){and°dONLNd¯ı˛) a°dONLNd    <|(,Z=bitmap image on the same page. The code for imaging patterns °dONLNdF|˛(,öallocates almost all of the°dONLNdb<_(8Z:available RAM for itself, so when the bitmap imaging code °dONLNdú_˛(8}"tries to allocate space, and there°dONLNdø<(ï(DZisn’t enough (and °dONLNd—ï(˛)YEit doesn’t know how to reclaim memory from the previous operation), a,
  3249. Courier°dONLNd(<4Ç(QZ
  3250. limitcheck°dONLNd!)Ç5à)F °dONLNd")à5˛)Eerror occurs. This problem exists in 2.0 LaserWriter ROMs. It will be°dONLNdh5<A~(]Z
  3251. improved but °dONLNdu5~Aê)Bnot°dONLNdx5êA&) fixed in the next ROM version.°dONLNdòM<YF(uZ4.°dONLNdõMNY≈)NIf a user chooses US Letter or B5 paper and has a different sized tray in the °dONLNdÈM≈Y˛(u„ printer, and°dONLNdˆY<e¿(ÅZSprints using manual feed, the LaserWriter will print assuming that the paper being °dONLNd    IY¿e˛(Åfi fed manually°dONLNd    Ve<qv(çZEis the same size as that in the tray. For example, if they have a US °dONLNd    õevq˛(çîletter tray in the LaserWriter°dONLNd    ∫q<}+(ôZ3and print a document formatted for B5 letter using °dONLNd    Ìq+}˛)Ô+manual feed, the image will not be centered°dONLNd
  3252. }<â\(•Zon the °dONLNd
  3253.  }\â˛) Wpage. The printer assumes that the manually fed paper is also US letter size and prints°dONLNd
  3254. xä<ñl(≤Z
  3255. the image °dONLNd
  3256. Çälñ‚)0Ppositioned accordingly, despite the driver’s instructions. This is a bug in the °dONLNd
  3257. “â‚ï˛(≤Note ¡X¡
  3258. (÷ZPR 5 - LaserWriter ROMs Bugs(÷1) of 2(ÏZM.PR.LaserWriterROMBugsˇ°¿Ù%%DSIDICT:_cv
  3259. currentdict /bu known {bu}if
  3260. userdict /_cv known not{userdict /_cv 30 dict put}if
  3261. _cv begin
  3262. /bdf{bind def}bind def
  3263. currentscreen/cs exch def/ca exch def/cf exch def
  3264. /setcmykcolor where{/setcmykcolor get /cvcmyk exch def}{/cvcmyk{1 sub 4 1 roll 3{3 index add neg dup 0 lt{pop 0}if 3 1 roll}repeat setrgbcolor pop}bdf }ifelse
  3265. /ss{//cf //ca //cs setscreen}bdf
  3266. /stg{ss setgray}bdf
  3267. /strgb{ss setrgbcolor}bdf
  3268. /stcmyk{ss cvcmyk}bdf
  3269. /min1{dup 0 eq{pop 1}if}bdf
  3270. end
  3271. currentdict /bn known {bn}if
  3272. †ø    F◊#ˇ ˇˇˇˇ#◊ 
  3273. IR,Times
  3274. .+6-Macintosh Technical Notes /4/˘
  3275. °dONLNd)§*Roperator in PostScript, which the driver uses for specifying the US letter and B5 °dONLNdR§)⁄(E¬ letter paper°dONLNd_)5∂(Q6!sizes. The workaround is to tell °dONLNdÄ)∂5⁄)û:the user to put an B5 tray in the printer when printing B5°dONLNdª5AL(]6?manually. This problem exists in the 1.0 and 2.0 ROMs and will °dONLNd˙5LA^(]jnot°dONLNd˝5^Añ)
  3276.  be fixed in °dONLNd
  3277. 5ñA⁄)8 the next ROM°dONLNdAM?(i6version.°dONLNd!YeÓ**By the way, an interesting, but annoying, °dONLNdKYÓe⁄)÷+occurance of this bug happens when manually°dONLNdweqq(ç6Eprinting Legal sized documents with the 4.0 LaserWriter driver. When °dONLNdºeqq⁄(çèthe Larger Print Area°dONLNd“r~¸(ö63option in the style dialog is deselected (which is °dONLNdr¸~ì)‰!the default) the driver uses the ,
  3278. Courier°dONLNd&qì}Ø)óNote°dONLNd*rØ~⁄)     operator°dONLNd4~ä´(¶6to specify the page size. When °dONLNdS~´ä⁄)ì<the user prints the document using manual feed, and has a US°dONLNdêäñ˜(≤64letter tray in the printer, the image is shifted up °dONLNdƒä˜ñ⁄)fl0on the page cutting off the top of the image. If°dONLNdıñ¢ (æ6(you tell the user to turn on the Larger °dONLNdñ ¢⁄)≤;Print Area option in the style dialog, the driver specifies°dONLNdY£Øt(À6the page size using °dONLNdm¢tÆó)\Legal°dONLNdr£óØÀ)#  instead of °dONLNd~¢ÀÆÁ)4Note°dONLNdÇ£ÁØâ)# and the image is printed properly.°dONLNd¶”flÇ(˚6Further Reference: ˛4˛˘°dONLNdπ‡*Ï.+
  3279. •°dONLNdª‡<Ï£)The Printing Manager°dONLNd–Ï*¯.(H•°dONLNd“Ï<¯ˆ)$PostScript Language Reference Manual°dONLNdˆÏˆ¯G)∫, Adobe Systems ¡4¡˘
  3280. (÷62) of 2(÷wPR 5 - LaserWriter ROMs Bugs+ M.PR.LaserWriterROMBugsˇ
  3281. †◊#ˇ ˇˇˇˇ#◊°d WORDS †å°d WORDR…†Ç 
  3282. /ZÅ#
  3283.     0Ià:µú9"{    ˇˇˇˇˇˇˇˇ#†ƒ°d
  3284. ONLNf˛†å°d1drw2…-·_ġˇˇˇˇˇè°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˙ó@†ò,Times
  3285. .WIQkWIQk+]BNew Technical Notes†ô°ddrw2:°„†ó°d1drw2eÙġˇˇˇˇˇP°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚ÄE¿†ò
  3286. Ä({ïDeveloper Support†ô°ddrw2:°„†ó°d`drw2-ÔˇˇˇˇˇˇKÔ- Z  ffZ°d1drw2 ¿˙ÈˇˇˇˇˇˇK°ñ x°ddrw2:°ddrw2:$°d4drw2:0°öˇÙĆò
  3287. 0(UÔ†ô°ddrw2:°„†ó°d1drw2ÔÊ˙ˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:    °öˇ˝Ä†ò
  3288.     l+&    ®†ô°ddrw2:°„†ó°d1drw2Â-¯yˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚Ä%†ò
  3289. BÄ(Z\    Macintosh†ô°ddrw2:°„†ó†ç°ddrw2D†É°dWORD†ç
  3290. IR.°dONLNdo<Ǩ(úZ*PR 6 - Using Low-Level Printing Calls With°dONLNd+Å<î*AppleTalk ImageWriters
  3291. °dONLNdBì<¢s*Printing
  3292. °dONLNdLÆ<∫t* Revised by:°dONLNdXÆÑ∫Û)HScott "ZZ" Zimmerman°dONLNdmÆ∏∫˛(÷÷
  3293. February 1988°dONLNd{∫<Δt(‚Z Revised by:°dONLNdà∫≈Δ˛(‚„
  3294. March 1988°dONLNdìΔ<“q(ÓZ Written by:°dONLNdüΔÑ“”)HGinger Jernigan °dONLNd∞ΔŒ“˛(ÓÏMay 1987 ˝X˝°dONLNdπÎ<˜”(ZRWhen you use the low-level printer driver to print, you don’t get the benefits of °dONLNd Δ˜˛(Ò    the error°dONLNd˜<Û(Z^checking that is done when you use the high-level Printing Manager. So, if the user prints to °dONLNds˜Û˛(an°dONLNdv<ã(+ZCAppleTalk ImageWriter (including an AppleTalk ImageWriter LQ) that °dONLNdπã˛(+©is busy printing another°dONLNd“<K(7Z:job, the driver doesn’t know whether the printer is busy, °dONLNd K˛(7i%offline, or disconnected.  Because of°dONLNd2<(.(DZ6this, PrError will return (and PrintErr will contain) ,
  3295. Courier°dONLNdh.'f)ÚabortErr°dONLNdpf(j)8.°dONLNdr4<@ë(\ZSince there is no °dONLNdÑ4ë@˛)UGway to tell when you are printing to an AppleTalk ImageWriter, the only°dONLNdÃ@<L{(hZDworkaround for this is to use high-level Printing Manager interface.°dONLNdp<|¶*0Further Reference: õXõ°dONLNd$}NâR+
  3296. •°dONLNd&}`â«)The Printing Manager ¡X¡
  3297. (÷ZAPR 6 - Using Low-Level Printing Calls With AppleTalk ImageWriters(÷1) of 1(ÏZM.PR.ImageWriterˇ°¿Ù%%DSIDICT:_cv
  3298. currentdict /bu known {bu}if
  3299. userdict /_cv known not{userdict /_cv 30 dict put}if
  3300. _cv begin
  3301. /bdf{bind def}bind def
  3302. currentscreen/cs exch def/ca exch def/cf exch def
  3303. /setcmykcolor where{/setcmykcolor get /cvcmyk exch def}{/cvcmyk{1 sub 4 1 roll 3{3 index add neg dup 0 lt{pop 0}if 3 1 roll}repeat setrgbcolor pop}bdf }ifelse
  3304. /ss{//cf //ca //cs setscreen}bdf
  3305. /stg{ss setgray}bdf
  3306. /strgb{ss setrgbcolor}bdf
  3307. /stcmyk{ss cvcmyk}bdf
  3308. /min1{dup 0 eq{pop 1}if}bdf
  3309. end
  3310. currentdict /bn known {bn}if
  3311. †øí◊#ˇ ˇˇˇˇ#◊°d WORDS †å°d WORDR…†Ç 
  3312. /ZÅ#
  3313.     0Ià:µú9"{    ˇˇˇˇˇˇˇˇ#†ƒ°d
  3314. ONLNf˛†å°d1drw2…-·_ġˇˇˇˇˇè°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˙ó@†ò,Times
  3315. .WIQkWIQk+]BNew Technical Notes†ô°ddrw2:°„†ó°d1drw2eÙġˇˇˇˇˇP°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚ÄE¿†ò
  3316. Ä({ïDeveloper Support†ô°ddrw2:°„†ó°d`drw2-ÔˇˇˇˇˇˇKÔ- Z  ffZ°d1drw2 ¿˙ÈˇˇˇˇˇˇK°ñ x°ddrw2:°ddrw2:$°d4drw2:0°öˇÙĆò
  3317. 0(UÔ†ô°ddrw2:°„†ó°d1drw2ÔÊ˙ˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:    °öˇ˝Ä†ò
  3318.     l+&    ®†ô°ddrw2:°„†ó°d1drw2Â-¯yˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚Ä%†ò
  3319. BÄ(Z\    Macintosh†ô°ddrw2:°„†ó†ç°ddrw2D†É°dWORD†ç
  3320. IR.°dONLNdo<Ç…(úZPR 7 - PrGeneral
  3321. °dONLNdÅ<ês*Printing
  3322. °dONLNdú<®t* Revised by:°dONLNd(ú≈®˛(ƒ„
  3323. March 1988°dONLNd3®<¥q(–Z Written by:°dONLNd?®Ñ¥Ã)HGinger Jenigan°dONLNdN®Œ¥˛(–ÏMay 1987°dONLNdW¿<Ãí(ËZAThe Printing Manager architecture has been expanded to include a °dONLNdò¿íÃ˛(Ë∞new procedure called,
  3324. Courier°dONLNd≠Ã<ÿ{(ıZ    PrGeneral°dONLNd∂Õ{Ÿø)?. The features °dONLNd≈ÕøŸ˛)DBdescribed here are advanced, special-purpose features, intended to°dONLNdŸ<Â(Z/solve specific problems for those applications °dONLNd7ŸÂ˛)‡.that need them. The calls to determine printer°dONLNdfÂ<Ò(
  3325. Z/resolution introduce a good deal of complexity °dONLNdïÂÒ˛)fi/into the application’s code, and should be used°dONLNd≈Ò<˝£(Zonly when necessary. (X(°dONLNd⁄<"ä*%GVersion 2.5 (and later) of the ImageWriter driver and version 4.0 (and °dONLNd!ä"˛(>®later) of the LaserWriter°dONLNd;#</¿(KZdriver implement a generic °dONLNdV#¿/m)Ñ"Printing Manager procedure called °dONLNdx"m.¨)≠    PrGeneral°dONLNdÅ#¨/˛)?. This procedure°dONLNdí/<;^(WZallows °dONLNdô/^;˛)"Vthe Print Manager to expand in functionality, by allowing printer drivers to implement°dONLNd<<H%(dZ1various new functions. The Pascal declaration of °dONLNd!;%Gd)È    PrGeneral°dONLNd*<dHr)? is:
  3326.     °dONLNd0T`_({~!PROCEDURE PrGeneral (pData: Ptr);
  3327. °dONLNdRk<wQ(ìZThe °dONLNdVjQvt)pData°dONLNd[ktwü)#C parameter is a pointer to a data block. The structure of the data °dONLNdûküw˛(ìΩblock is declared as°dONLNd≥w<Éc(üZfollows:
  3328.     °dONLNdΩè`ö™+$BTGnlData = RECORD {1st 8 bytes are common for all PrGeneral calls)°dONLNdô`§*
  3329.     iOpCode   : INTEGER;  {input}°dONLNd#£`Æ*
  3330. !   iError    : INTEGER;  {output}°dONLNdF≠`∏Z*
  3331. 2   lReserved : LONGINT;  {reserved for future use}°dONLNdz∑`¬_*
  3332. 3   {more fields here, depending on particular call}°dONLNdØ¡`Ãt*
  3333. END;
  3334. °dONLNd¥ÿ<‰ä(ZThe first field is °dONLNd«ÿä‰fl)Na 2-byte opcode, °dONLNdÿ◊fl„)UiOpCode°dONLNdflÿ‰˛)13, which acts like a routine selector. The currently°dONLNd‰<Ù( Z&available opcodes are described below.°dONLNd:˝<    Q*The °dONLNd>˝Q    Í)"second field is the error result, °dONLNd`¸Í)ôiError°dONLNdf˝    ˛)*1, which is returned by the print code. This error°dONLNdò
  3335. <€(2Z$only reflects error conditions that °dONLNdº
  3336. €.)üoccur during the °dONLNdÕ    .m)S    PrGeneral°dONLNd÷
  3337. m˛)? call. For example, if you use°dONLNdı<#(?Z1an opcode that isn’t implemented in a particular °dONLNd&#ø)·#printer driver then you will get a °dONLNdIø"˛)¢    OpNotImpl°dONLNdS#</W(KZerror.°dONLNdZ;<GÍ*&Here are the errors currently defined:
  3338.     °dONLNdÇS`^y+$CONST°dONLNdä]`hZ*
  3339. 2   noErr = 0;                 {everything’s hunky}°dONLNdæg`r»*
  3340. H   NoSuchRsl = 1;             {the resolution you chose isn’t available}°dONLNdq`|æ*
  3341. F   OpNotImpl = 2;             {the driver doesn’t support this opcode} ¡X¡
  3342. (÷ZPR 7 - PrGeneral(÷1) of 7(ÏZM.PR.PRGeneralˇ°¿Ù%%DSIDICT:_cv
  3343. currentdict /bu known {bu}if
  3344. userdict /_cv known not{userdict /_cv 30 dict put}if
  3345. _cv begin
  3346. /bdf{bind def}bind def
  3347. currentscreen/cs exch def/ca exch def/cf exch def
  3348. /setcmykcolor where{/setcmykcolor get /cvcmyk exch def}{/cvcmyk{1 sub 4 1 roll 3{3 index add neg dup 0 lt{pop 0}if 3 1 roll}repeat setrgbcolor pop}bdf }ifelse
  3349. /ss{//cf //ca //cs setscreen}bdf
  3350. /stg{ss setgray}bdf
  3351. /strgb{ss setrgbcolor}bdf
  3352. /stcmyk{ss cvcmyk}bdf
  3353. /min1{dup 0 eq{pop 1}if}bdf
  3354. end
  3355. currentdict /bn known {bn}if
  3356. †øP◊#ˇ ˇˇˇˇ#◊ 
  3357. IR,Times
  3358. .+6-Macintosh Technical Notes /4/˘
  3359. °dONLNd*W*After calling ,
  3360. Courier°dONLNdW)ñ)?    PrGeneral°dONLNdñ*‘)?  you should °dONLNd#‘*)>
  3361. always check °dONLNd0)K)FPrError°dONLNd7K*a)1. If °dONLNd<a)Ñ)noErr°dONLNdAÑ*⁄)# is returned, then°dONLNdT+7w(S6you can proceed. If °dONLNdh*w6ƒ)_ ResNotFound°dONLNds+ƒ7L)M is returned, then the current °dONLNdí+L7⁄)àprinter driver doesn’t support°dONLNd±7CW(`6    PrGeneral°dONLNd∫8WD_)?5 and you should proceed appropriately. See Technical °dONLNdÔ8_D⁄(`}Note #118 for details on°dONLNdDP(l61checking errors returned by the Printing Manager.°dONLNd;\hB*IError°dONLNdA]Biì)*J is followed by a four byte reserved field (that means don’t use it). The °dONLNdã]ìi⁄(Ö±contents of the°dONLNdõiu∂(ë6"rest of the data block depends on °dONLNdΩi∂u⁄)û>the opcode that the application uses. There are currently five°dONLNd¸uÅ-(ù68opcodes used by the ImageWriter and LaserWriter drivers.
  3362. °dONLNd5ô®m*' The Opcodes
  3363. °dONLNdAµ¡˛*3Initially, the following calls are implemented via °dONLNdt¥˛¿=)Ê    PrGeneral°dONLNd}µ=¡@)?:°dONLNdÄŒ<⁄F(ˆZ•  °dONLNdÉÕFŸå)
  3364.  
  3365. GetRslData°dONLNdçŒå⁄Û)F (get resolution data): °dONLNd•ÕÛŸ@)g iOpCode = 4°dONLNd≤€<ÁF(Z•  °dONLNdµ⁄FÊp)
  3366. SetRsl°dONLNdª€pÁ¿)* (set resolution): °dONLNdŒ⁄¿Ê
  3367. )P iOpCode = 5°dONLNd€Ë<ÙF(Z•  °dONLNdfiÁFÛÖ)
  3368.     DraftBits°dONLNdÁËÖÙ˝)? (bitmaps in draft mode): °dONLNdÁ˝ÛJ)x iOpCode = 6°dONLNdı<F(Z•  °dONLNdÙFì)
  3369. noDraftBits°dONLNdıì)M (no bitmaps in draft mode): °dONLNd9Ùg)á iOpCode = 7°dONLNdF<F(*Z•  °dONLNdIF
  3370. w)
  3371. GetRotn°dONLNdPwΩ)1 (get rotation): °dONLNdaΩ
  3372. 
  3373. )F iOpCode = 8°dONLNdm'-(C6The °dONLNdq-&s)
  3374. GetRslData°dONLNd{s'ä)F and °dONLNdÄä&¥)SetRsl°dONLNdÜ¥'i)*( allow the application to find out what °dONLNdÆi'⁄)µphysical resolutions the°dONLNd«(4˚(P6/printer supports, and then specify a supported °dONLNdˆ(˚43)„ resolution. °dONLNd'33r)8    DraftBits°dONLNd (r4ç)? and °dONLNd'ç3⁄) noDraftBits°dONLNd5A<(]6invoke °dONLNd#5<AÄ)$?a new feature of the ImageWriter, allowing bitmaps (imaged via °dONLNdb4Ä@∏(]ûCopyBits°dONLNdj5∏A⁄)8) to be°dONLNdrBNÇ(j6printed in draft mode. °dONLNdâAÇM≥)jGetRotn°dONLNdêB≥N±)15 lets an application know whether landscape has been °dONLNd≈B±N⁄)˛    selected.°dONLNdœNZ.(v6:Below is a detailed description of how each routine works.
  3375. °dONLNd
  3376. rņ*'The GetRslData Call
  3377. °dONLNdçô^*
  3378. GetRslData°dONLNd(é^öi)F (°dONLNd*çiôæ) iOpCode = 4°dONLNd5éæö†)U-) returns a record that lets the application °dONLNdbé†ö⁄)‚    know what°dONLNdlõß≠(√6resolutions are supported by °dONLNdâõ≠ß∞)ï2the current printer. The application can then use °dONLNdªö∞¶⁄(√ŒSetRsl°dONLNd¬ß≥ô(œ6T(description follows) to tell the printer driver which one it will use. This is the °dONLNdßô≥⁄(œ∑
  3379. format of the°dONLNd$¥¿à(‹6input data block for the °dONLNd=≥àøŒ)p
  3380. GetRslData°dONLNdG¥Œ¿‰)F call:
  3381.     °dONLNdOÃ<◊á(ÛZTRslRg = RECORD°dONLNd_î◊ )l{used in TGetRslBlk}°dONLNdv÷`·U(˝~1{0 if printer only supports discrete resolutions}°dONLNd™‡`Îó*
  3382. iMin, iMax:°dONLNd∂‡®Ζ)HInteger;°dONLNd¿Í<ıP(ZEND;°dONLNdΔ˛<    å*TRslRec = RECORD°dONLNd◊˛®     )l{used in TGetRslBlk}°dONLNdÓ`x(/~8iXRsl, iYRsl: Integer; {a discrete, physical resolution}°dONLNd(<P(9ZEND;°dONLNd.(<3õ*TGetRslBlk = RECORD°dONLNdB(®3H)l {data block for GetRslData call}°dONLNde2`=à(Y~iOpCode:°dONLNdn2®=–)HInteger;°dONLNdw2=c)H{input; = getRslDataOp}°dONLNdë<`GÉ(c~iError:°dONLNdô<®G–)HInteger;°dONLNd¢<G)H{output}°dONLNd≠F`Qí(m~
  3383. lReserved:°dONLNd∏F®Q–)HLongInt;°dONLNd¡FQm)H{reserved for future use}°dONLNd›P`[à(w~iRgType:°dONLNdÊP®[–)HInteger;°dONLNdÔP[h)H{output; version number}°dONLNd
  3384. Z`eÉ(Å~XRslRg:°dONLNdZ®eÀ)HTRslRg;°dONLNdZeê)H {output; range of X resolutions}°dONLNd=d`oÉ(ã~YRslRg:°dONLNdEd®oÀ)HTRslRg;°dONLNdMdoê)H {output; range of Y resolutions}°dONLNdpn`yó(ï~ iRslRecCnt:°dONLNd|n®y–)HInteger;°dONLNdÖnyï)H!{output; how many RslRecs follow}°dONLNd©x`Éç(ü~    rgRslRec:°dONLNd≥x®Éò)H0ARRAY[1..27] OF TRslRec;  {output; number filled ¡4¡˘
  3385. (÷62) of 7(÷≥PR 7 - PrGeneral(ϱM.PR.PRGeneralˇX◊#ˇ ˇˇˇˇ#◊ 
  3386. IR,Times
  3387. .+Z-Developer Support Center(-Ê October 1990 /X/,
  3388. Courier
  3389.     °dONLNd<(n(DZ
  3390. depends on°dONLNd '<2'*
  3391. /                                               °dONLNd<'\2ù(Nz
  3392. printer type}°dONLNdK1`<t(X~END;
  3393. °dONLNdPH<TQ(pZThe °dONLNdTGQSÇ)iRgType°dONLNd[HÇT®)1
  3394.  field is °dONLNdeH®T˛)&Hmuch like a version number; it determines the interpretation of the data°dONLNdÆU<a∂(}Zthat follows. At present, °dONLNd»U∂a¿)za °dONLNd T¿`Ò)
  3395. iRgType°dONLNd—UÒa˛)16 value of 1 applies both to the LaserWriter and to the°dONLNda<m{(âZ ImageWriter.°dONLNdz<Üü*LFor variable-resolution printers like the LaserWriter, the resolution range °dONLNdazüÜæ(¢Ωfields °dONLNdhyæÖË)XRslRg°dONLNdnzËܲ)* and°dONLNdsÜ<íf(ØZYRslRg°dONLNdyáfì-)*' express the ranges of values to which °dONLNd†á-ì˛)«'the X and Y resolutions can be set. For°dONLNd»ì<ü](ªZ>discrete-resolution printers like the ImageWriter, the values °dONLNdì]ü˛(ª{"in the resolution range fields are°dONLNd)ü<´T(«Zzero.°dONLNd/∑<√[*Note:°dONLNd4∑[√ )& In general, X and Y in these records °dONLNdZ∑ √⁄)±-are the horizontal and vertical directions of°dONLNdà√`œq(Î~the °dONLNdå√qœó)printer°dONLNdì√óœˆ)&, not the document! °dONLNdß√ˆœ⁄)_0In landscape orientation, X is horizontal on the°dONLNdÿœ`€ (˜~%printer but vertical on the document.°dONLNd˛Á<Û&(Z2After the resolution range information there is a °dONLNd0Á&Û˛)Í)word which gives the number of resolution°dONLNdZÛ<ˇ¡(ZRrecords that contain information. These records indicate the physical resolutions °dONLNd¨Û¡ˇ˛(fl at which the°dONLNdπˇ< œ('ZWprinter can actually print dots. Each resolution record gives an X value and a Y value.°dONLNd<$É*When you call °dONLNdÉ#¬)G    PrGeneral°dONLNd(¬$í)?/ you pass in a data block that looks like this:†Ç†å
  3396. O’'°
  3397. 4Rÿei8°ñz°öˇ˛†ò,     Helvetica
  3398.     ÿÃÿðdONLNdˇˇ+õ1 word†ô†ó°ñz°öˇ˛†ò°dONLNdˇˇ(^fi
  3399. OpCode = 4†ô†ó4dÿwi8°ñz2izrô°öˇ˛†ò°dONLNdˇˇ+ù1 word†ô†ó°ñz°öˇ˛,†ò°dONLNdˇˇ(pfi
  3400. Error Code†ô†ó°ñz°öˇ˛†ò°dONLNdˇˇ+ù2 words†ô†ó4vÿâi8°ñz°öˇ˛†ò°dONLNdˇˇ(ÇfiReserved†ô†ó4àÿõi8°ñz°öˇ˛†ò°dONLNdˇˇ+ù1 word†ô†ó°ñz°öˇ˛ †ò°dONLNdˇˇ(îfi
  3401. RangeType = 1†ô†ó°ñz°öˇ˛†ò°dONLNdˇˇ+ù-2 words†ô†ó4µÿ—i8°ñz°ö,†ò°dONLNdˇˇ(¿›Y Resolution Range:
  3402. †ô°öˇ˘,†ò°dONLNdˇˇ*    min =0, max = 0†ô†ó°ñz°öˇ˛†ò°dONLNdˇˇ+û1 word†ô†ó4–ÿ„i8°ñz°öˇ˛;†ò°dONLNdˇˇ(€›Resolution Record Count =0†ô†ó°ñz°öˇ˛†ò°dONLNdˇˇ+û2 words†ô†ó4‚ÿ˛i8°ñz°ö.†ò°dONLNdˇˇ(Ì›Resolution Record #1:
  3403. †ô°öˇ˘.†ò°dONLNdˇˇ*     X = 0, Y = 0†ô†ó4öÿ∂i8°ñz°ö,†ò°dONLNdˇˇ(£›X Resolution Range:
  3404. †ô°öˇ˘,†ò°dONLNdˇˇ*    min = 0, max = 0†ô†ó°ñz°öˇ˛†ò°dONLNdˇˇ(©{2 words†ô†ó°ñz°öˇ˛8†ò°dONLNdˇˇ(› Resolution Record #2..27†ô†ó††°§
  3405. "ÿ-¸#$#$#¯†£
  3406. O’'°"ÿ#ˇ###################################ˇ###ˇ##ˇ##ˇ#ˇ#ˇ#ˇ##ˇ†°"ÿÓ"˝h†ç†É
  3407. IR
  3408. °dONLNdX <,4(HZ5Below is the data block returned for the LaserWriter: ¡X¡
  3409. *éPR 7 - PrGeneral(÷3) of 7(ÏZM.PR.PRGeneralˇ◊#ˇ ˇˇˇˇ#◊ 
  3410. IR,Times
  3411. .+6-Macintosh Technical Notes /4/˘†Ç†å†å
  3412. <≥È{
  3413. 4=¥PE8°ñ°öˇ˛†ò,     Helvetica
  3414.     ≠»≠»°dONLNdˇˇ(JW1 word†ô†ó°ñ°öˇ˛C†ò°dONLNdˇˇ(J∫
  3415. OpCode = 4†ô†ó†ç†å4O¥bE8°ñ2TV_u°öˇ˛†ò°dONLNdˇˇ+ù1 word†ô†ó°ñ°öˇ˛C†ò°dONLNdˇˇ(\∫Error Code (0 = okay)†ô†ó†ç†å°ñ°öˇ˛†ò°dONLNdˇˇ+ù2 words†ô†ó4a¥tE8°ñ°öˇ˛C†ò°dONLNdˇˇ(n∫Reserved†ô†ó†ç†å4s¥ÜE8°ñ°öˇ˛†ò°dONLNdˇˇ+ù1 word†ô†ó°ñ°öˇ˛C†ò°dONLNdˇˇ(Ä∫
  3416. RangeType = 1†ô†ó†ç†å°ñ°öˇ˛†ò°dONLNdˇˇ+ù-2 words†ô†ó4†¥ºE8°ñ°öC†ò°dONLNdˇˇ(¨πY Resolution Range:
  3417. †ô°öˇ¯C†ò°dONLNdˇˇ* min = 72, max = 1500†ô†ó†ç†å°ñ°öˇ˛†ò°dONLNdˇˇ+û1 word†ô†ó4ª¥ŒE8°ñ°öˇ˛C†ò°dONLNdˇˇ(«πResolution Record Count = 1†ô†ó†ç†å°ñ°öˇ˛†ò°dONLNdˇˇ+û2 words†ô†ó4Õ¥ÈE8°ñ°öC†ò°dONLNdˇˇ(ŸπResolution Record #1:
  3418. †ô°öˇ¯C†ò°dONLNdˇˇ* X = 300, Y = 300†ô†ó†ç†å4Ö¥°E8°ñ°öC†ò°dONLNdˇˇ(èπX Resolution Range:
  3419. †ô°öˇ¯C†ò°dONLNdˇˇ* min = 72, max = 1500†ô†ó°ñ°öˇ˛†ò°dONLNdˇˇ(ïW2 words†ô†ó†ç†ç†É
  3420. IR
  3421. °dONLNd‚Ó0(
  3422. 6<Note that all the resolution range numbers happen to be the °dONLNd<‚0Ó⁄(
  3423. N$same for this printer. There is only°dONLNdaÓ˙“(6]one resolution record, which gives the physical X and Y resolutions of the printer (300x300).°dONLNdø*5Below is the data block returned for the ImageWriter.†Ç†å†å
  3424. =≥;{4>¥QE8°ñ°öˇ˛†ò
  3425.     ˛»˛»°dONLNdˇˇ(KW1 word†ô†ó°ñ°öˇ˛C†ò°dONLNdˇˇ(K∫
  3426. OpCode = 4†ô†ó†ç†å4P¥cE8°ñ2UV`u°öˇ˛†ò°dONLNdˇˇ+ù1 word†ô†ó°ñ°öˇ˛C†ò°dONLNdˇˇ(]∫Error Code (0 = okay)†ô†ó†ç†å°ñ°öˇ˛†ò°dONLNdˇˇ+ù2 words†ô†ó4b¥uE8°ñ°öˇ˛C†ò°dONLNdˇˇ(o∫Reserved†ô†ó†ç†å4t¥áE8°ñ°öˇ˛†ò°dONLNdˇˇ+ù1 word†ô†ó°ñ°öˇ˛C†ò°dONLNdˇˇ(Å∫
  3427. RangeType = 1†ô†ó†ç†å°ñ°öˇ˛†ò°dONLNdˇˇ+ù-2 words†ô†ó4°¥ΩE8°ñ°öC†ò°dONLNdˇˇ(≠πY Resolution Range:
  3428. †ô°öˇ¯C†ò°dONLNdˇˇ* min = 0, max = 0†ô†ó†ç†å°ñ°öˇ˛†ò°dONLNdˇˇ+û1 word†ô†ó4º¥œE8°ñ°öˇ˛C†ò°dONLNdˇˇ(»πResolution Record Count = 4†ô†ó†ç†å°ñ°öˇ˛†ò°dONLNdˇˇ+û2 words†ô†ó4Œ¥ÍE8°ñ°öC†ò°dONLNdˇˇ(⁄πResolution Record #1:
  3429. †ô°öˇ¯C†ò°dONLNdˇˇ* X = 72, Y = 72†ô†ó†ç†å4Ü¥¢E8°ñ°öC†ò°dONLNdˇˇ(êπX Resolution Range:
  3430. †ô°öˇ¯C†ò°dONLNdˇˇ* min =0, max = 0†ô†ó°ñ°öˇ˛†ò°dONLNdˇˇ(ñW2 words†ô†ó†ç†å°ñ°öˇ˛†ò°dONLNdˇˇ*`2 words†ô†ó4È¥E8°ñ°öC†ò°dONLNdˇˇ(ıπResolution Record #2:
  3431. †ô°öˇ¯C†ò°dONLNdˇˇ* X =144, Y = 144†ô†ó†ç†å°ñ°öˇ˛†ò°dONLNdˇˇ+û2 words†ô†ó4¥ E8°ñ°öC†ò°dONLNdˇˇ(πResolution Record #3:
  3432. †ô°öˇ¯C†ò°dONLNdˇˇ* X = 80, Y = 72†ô†ó†ç†å°ñ°öˇ˛†ò°dONLNdˇˇ+û2 words†ô†ó4¥;E8°ñ°öC†ò°dONLNdˇˇ(+πResolution Record #4:
  3433. †ô°öˇ¯C†ò°dONLNdˇˇ* X = 160, Y = 144†ô†ó†ç†ç†É
  3434. IR
  3435. °dONLNdı4@â(\6All the resolution range °dONLNd4â@⁄)qGvalues are zero, because only discrete resolutions can be specified for°dONLNdV@Lµ(h6[this printer. There are four resolution records giving these discrete physical resolutions.°dONLNd≤YeF*
  3436. Note that ,
  3437. Courier°dONLNdºXFdå).
  3438. GetRslData°dONLNdΔYåeÖ)F6 always returns the same information for a particular °dONLNd¸YÖe⁄)˘printer type—it is°dONLNdeq*(ç6not°dONLNde*qÖ)I dependent on what the user does or on printer configuration information. ¡4¡˘
  3439. (÷64) of 7(÷≥PR 7 - PrGeneral(ϱM.PR.PRGeneralˇÊ◊#ˇ ˇˇˇˇ#◊ 
  3440. IR,Times
  3441. .+Z-Developer Support Center(-Ê October 1990 /X/
  3442. °dONLNd<,£(HZThe SetRsl Call,
  3443. Courier
  3444. °dONLNd8<Df*SetRsl°dONLNd9fEp)* (°dONLNd8pD°)
  3445. iOpCode°dONLNd9°Ea)1% = 5) is used to specify the desired °dONLNdD9aE˛)¿imaging resolution, after using°dONLNddE<QÇ(nZ
  3446. GetRslData°dONLNdnFÇRÒ)FO to determine a workable pair of values. Below is the format of the data block:
  3447.     °dONLNdø^`iú(Ö~ TSetRslBlk =°dONLNdÃ^®iΔ)HRECORD°dONLNd”^ÃiX)${data block for SetRsl call}°dONLNdÚhÑs¨(è¢iOpCode:°dONLNd˚hÃsÙ)HInteger;°dONLNdhss)H{input; = setRslOp}°dONLNdrÑ}ß(ô¢iError:°dONLNd"rÃ}Ù)HInteger;°dONLNd+r}<)H{output}°dONLNd6|Ñá∂(£¢
  3448. lReserved:°dONLNdA|ÃáÙ)HLongInt;°dONLNdJ|áë)H{reserved for future use}°dONLNdfÜÑëß(≠¢hPrint:°dONLNdnÜÃëÙ)HTHPrint;°dONLNdwÜë◊)H'{input; handle to a valid print record}°dONLNd°êÑõ¢(∑¢iXRsl:°dONLNd®ê®õ–)$Integer;°dONLNd±êõÅ)H{input; desired X resolution}°dONLNd—öÑ•¢(¡¢iYRsl:°dONLNdÿö®•–)$Integer;°dONLNd·ö•Å)H{input; desired Y resolution}°dONLNd§`Øt(À~END;
  3449. °dONLNd∫<Δf(„ZhPrint°dONLNd ªf«·)* should be the handle °dONLNd!ª·«˛){4of a print record that has previously been passed to°dONLNdV«<”Ç(Z
  3450. PrValidate°dONLNd`»Ç‘^)F/. If the call executes successfully, the print °dONLNdè»^‘˛)‹record is updated with the new°dONLNdÆ‘<‡”(¸ZVresolution; the data block comes back with 0 for the error and is otherwise unchanged.°dONLNdÌ<˘i*?However, if the desired resolution is not supported, the error °dONLNdDÌi˘ñ(á
  3451. is set to °dONLNdNÏñ¯’)-    noSuchRsl°dONLNdWÌ’˘˛)? and the°dONLNd`˘<F(!Z=resolution fields are set to the printer’s default resolution°dONLNdû<:*5Note that you can undo the effect of a previous call °dONLNd”:H)˛to °dONLNd÷Hr)SetRsl°dONLNd‹r˛)* by making another call that°dONLNd˘<*π(FZRspecifies an unsupported resolution (such as 0x0), forcing the default resolution.
  3452. °dONLNdLB<Q∏*'The DraftBits Call
  3453. °dONLNd_]<i{*    DraftBits°dONLNdh^{jÉ)? (°dONLNdj]Éi¥)iOpCode°dONLNdq^¥jF)1 = 6) is implemented on both °dONLNdé^Fj˛)í$the ImageWriter and the LaserWriter.°dONLNd≥j<v(íZ%(On the LaserWriter it does nothing, °dONLNdÿjv˛)¥5since the LaserWriter is always in draft mode and can°dONLNdv<ÇZ(ûZ=always print bitmaps.) Below is the format of the data block:
  3454.     °dONLNdMé`ô°+$
  3455. TDftBitsBlk =°dONLNd[é®ôΔ)HRECORD°dONLNdbéÃôº)$0{data block for DraftBits and NoDraftBits calls}°dONLNdïòÑ£¨(ø¢iOpCode:°dONLNdûòãÙ)HInteger;°dONLNdßò£◊)H'{input; = draftBitsOp or noDraftBitsOp}°dONLNd—¢Ñ≠ß(…¢iError:°dONLNdŸ¢Ã≠Ù)HInteger;°dONLNd‚¢≠<)H{output}°dONLNd̨Ñ∑∂(”¢
  3456. lReserved:°dONLNd¯¨Ã∑Ù)HLongInt;°dONLNd¨∑ë)H{reserved for future use}°dONLNd∂Ñ¡ß(›¢hPrint:°dONLNd%∂áÙ)HTHPrint;°dONLNd.∂¡◊)H'{input; handle to a valid print record}°dONLNdW¿`Àt(Á~END;
  3457. °dONLNd\÷<‚f(ˇZhPrint°dONLNdb◊f„·)* should be the handle °dONLNdx◊·„˛){4of a print record that has previously been passed to°dONLNd≠„<ÔÇ( Z
  3458. PrValidate°dONLNd∑‰ÇÜ)F.°dONLNdπ¸<($Z.This call forces draft-mode (i.e., immediate) °dONLNdÁ¸˛)‘2printing, and will allow bitmaps to be printed via°dONLNd<t(1ZCopyBits°dONLNd"    tÈ)8R calls. The virtue of this is that you avoid spooling large masses of bitmap data °dONLNdt    È˛(1onto°dONLNdy<!(=Z.the disk, and you also get better performance.°dONLNd®-<9÷*!The following restrictions apply:°dONLNd ENQR+•°dONLNdÃE[Qª)
  3459. IThis call should be made before bringing up the print dialogs because it °dONLNdEªQ⁄(mŸaffects°dONLNdR[^Œ(zytheir appearance. On °dONLNd2RŒ^U)sthe ImageWriter, calling °dONLNdKQU]î)á    DraftBits°dONLNdTRî^⁄)?
  3460.  disables the°dONLNdb^[jg(Üy;landscape icon in the  Style dialog, and the Best, Faster, °dONLNdù^gj⁄(ÜÖand Draft buttons in the°dONLNd∂j[vê(íy Job dialog.°dONLNd¬ÇNéR(™l•°dONLNdƒÇ[éÎ)
  3461.  If the printer does not support °dONLNd‰ÇÎé⁄)ê1draft mode, already prints bitmaps in draft mode,°dONLNd    é[ö\(∂y:or does not  print bitmaps at all, this call does nothing. ¡X¡
  3462. (÷ZPR 7 - PrGeneral(÷5) of 7(ÏZM.PR.PRGeneralˇ:◊#ˇ ˇˇˇˇ#◊ 
  3463. IR,Times
  3464. .+6-Macintosh Technical Notes /4/˘
  3465. °dONLNd)*5.+$•°dONLNd)75Á)
  3466. %Only text and bitmaps can be printed.°dONLNd(A*M.(iH•°dONLNd*A7M[)
  3467. =As in the normal draft mode, landscape format is not allowed.°dONLNdhY*e.(ÅH•°dONLNdjY7e>)
  3468. 7Everything on the page must be strictly Y-sorted, i.e. °dONLNd°Y>e∂(Å\no reverse paper motion°dONLNdπe7qì(çUbetween one string °dONLNdÃeìq∂)\;or bitmap and the next. Note that this means you can’t have°dONLNdq7}[(ôUtwo or °dONLNdq[}∂)$Emore objects (text or bitmaps) side by side; the top boundary of each°dONLNdU}7âi(•UAobject must be no higher than the bottom of the preceding object.°dONLNdóï°±(Ω6#The last restriction is important. °dONLNd∫ï±°⁄)ôBIf you violate it, you will not like the results. But note that if°dONLNd˝°≠…(…6"you want two or more bitmaps side °dONLNd°…≠⁄)±5by side, you can combine them into one before calling,
  3469. Courier°dONLNdU≠πP(÷6CopyBits°dONLNd]ÆP∫S)8 °dONLNd^ÆS∫⁄)Tto print the result. Similarly, if you are just printing bitmaps you can rotate them°dONLNd≥∫ΔŒ(‚6'yourself to achieve landscape printing.
  3470. °dONLNd€fiÌß*'The NoDraftBits Call
  3471. °dONLNd˘e* NoDraftBits°dONLNd˚˙el)M (°dONLNd˝˘lù)iOpCode°dONLNd˙ùw)1- = 7) is implemented on both the ImageWriter °dONLNd1˙w⁄)⁄and the LaserWriter.°dONLNdFÃ(.6%(On the LaserWriter it does nothing, °dONLNdkÃ⁄)¥5since the LaserWriter is always in draft mode and can°dONLNd°P(;6@always print bitmaps.) The format of the data block is the same °dONLNd·Põ(;nas that for the °dONLNdÒõ⁄)K    DraftBits°dONLNd˚+,(G6call.°dONLNd8D¯*.This call cancels the effect of any preceding °dONLNd/7¯C7)‡    DraftBits°dONLNd887D<)? °dONLNd98<D⁄)call. If there was no preceding°dONLNdYDPW(m6    DraftBits°dONLNdbEWQô)?C call, or the printer does not support draft-mode printing anyway, °dONLNd•EôQ⁄(m∑this call does°dONLNd¥Q]@(y6nothing.
  3472. °dONLNdΩuÑå*'The GetRotn Call
  3473. °dONLNdŒêúI*GetRotn°dONLNd’ëIùQ)1 (°dONLNd◊êQúÇ)iOpCode°dONLNdfiëÇùL)1( = 8) is implemented on the ImageWriter °dONLNdëLù⁄) and LaserWriter. Here is the°dONLNd#ù©ã(≈6format of the data block:
  3474.     °dONLNd>µ<¿}+$
  3475. TGetRotnBlk =°dONLNdLµÑ¿¢)HRECORD°dONLNdSµ®¿9)${data block for GetRotn call}°dONLNdsø` à(Ê~iOpCode:°dONLNd|ø® –)HInteger;°dONLNdÖø T)H{input; = getRotnOp}°dONLNdú…`‘É(~iError:°dONLNd§…®‘–)HInteger;°dONLNd≠…‘)H{output}°dONLNd∏”`fií(˙~
  3476. lReserved:°dONLNd√”®fi–)HLongInt;°dONLNdÔfim)H{reserved for future use}°dONLNdË›`ËÉ(~hPrint:°dONLNd›®Ë–)HTHPrint;°dONLNd˘›Ë≥)H'{input; handle to a valid print record}°dONLNd#Á`Úó(~ fLandscape:°dONLNd/Á®Ú–)HBoolean;°dONLNd8ÁÚ^)H{output; Boolean flag}°dONLNdQÒ`¸~(~bXtra:°dONLNdXÒѸª)$ SignedByte;°dONLNdeÒ¸")l
  3477. {reserved}°dONLNdq˚<P("ZEND;
  3478. °dONLNdvB(:6hPrint°dONLNd|Bó)* should be the °dONLNdãó⁄)U;handle to a print record that has previously been passed to°dONLNd«*^(G6
  3479. PrValidate°dONLNd—^+b)F.°dONLNd”8D.(`6?If landscape orientation is selected in the print record, then °dONLNd7.Ct(`L
  3480. fLandscape°dONLNd8tDò)F     is true. ¡4¡˘
  3481. (÷66) of 7(÷≥PR 7 - PrGeneral(ϱM.PR.PRGeneralˇ 8◊#ˇ ˇˇˇˇ#◊ 
  3482. IR,Times
  3483. .+Z-Developer Support Center(-Ê October 1990 /X/
  3484. °dONLNd<,0(HZ How To Use The PrGeneral Opcodes
  3485. °dONLNd!9<EQ*The ,
  3486. Courier°dONLNd%8QD{)SetRsl°dONLNd+9{Eí)* and °dONLNd08íD—)    DraftBits°dONLNd99—E‘)? °dONLNd:9‘E˛)?calls may require the print code to suppress certain options in°dONLNdzE<Qû(mZLthe Style and/or Job dialogs, therefore they should always be called before °dONLNdΔEûQ˛(mºany call to the Style°dONLNd‹Q<]e(yZ@or Job dialogs. An application might use these calls as follows:°dONLNdjNvR+•°dONLNdj[v˘)
  3487. "Get a new print record by calling °dONLNdAi˘uM)û PrintDefault°dONLNdMjMvÖ)T
  3488. , or take an °dONLNdZjÖv⁄)8existing one from°dONLNdlw[ɪ(üya document and call °dONLNdÄvªÇ)`
  3489. PrValidate°dONLNdäwÉ)F on it.°dONLNdíêNúR(∏l•°dONLNdîê[úr)
  3490. Call °dONLNdôèrõ∏)
  3491. GetRslData°dONLNd£ê∏úO)F! to find out what the printer is °dONLNdƒêOú⁄)ócapable of, and decide what°dONLNd‡ù[©‘(≈yresolution to  use. Check °dONLNd˙ú‘®)yPrError°dONLNdù©J)1 to be sure the °dONLNdúJ®â)E    PrGeneral°dONLNdùâ©ü)? call °dONLNd ùü©⁄) is supported°dONLNd-™[∂=(“y5on  this version of the  print code; if the error is °dONLNdb©=µä)‚ ResNotFound°dONLNdm™ä∂⁄)M, you have older°dONLNd~∂[¬ (fiyPprint code and must print  accordingly. But if the PrError return is 0, proceed:°dONLNdœœN€R(˜l•°dONLNd—œ[€q)
  3492. Call °dONLNd÷Œq⁄õ)SetRsl°dONLNd‹œõ€∑)*> with the print record and the desired resolution if you wish.°dONLNdËNÙR(l•°dONLNdË[Ùq)
  3493. Call °dONLNd"ÁqÛ∞)    DraftBits°dONLNd+Ë∞ÙÃ)?= to invoke the printing of bitmaps in draft mode if you wish.°dONLNdi<
  3494. ø()ZNote that if you call either °dONLNdÜø È)ÉSetRsl°dONLNdåÈ
  3495. ˚)* or °dONLNdê˚ :)    DraftBits°dONLNdô:
  3496. õ)?, you should do so °dONLNd¨õ
  3497. ˛)abefore the user sees°dONLNd¡
  3498. <≈(5Zeither of the printing dialogs.°dONLNd·=<I¶*0Further Reference: hXh°dONLNdÙJNVR+
  3499. •°dONLNdˆJ`V«)The Printing Manager ¡X¡
  3500. (÷ZPR 7 - PrGeneral(÷7) of 7(ÏZM.PR.PRGeneralˇÃ◊#ˇ ˇˇˇˇ#◊†Ç 
  3501. /ZÅ#
  3502.     0Ià:µú9"{    ˇˇˇˇˇˇˇˇ#†ƒ°d
  3503. ONLNf˛†å°d1drw2…-·_ġˇˇˇˇˇè°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˙ó@†ò,Times
  3504. .R…R…+]BNew Technical Notes†ô°ddrw2:°„†ó°d1drw2eÙġˇˇˇˇˇP°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚ÄE¿†ò
  3505. ({ïDeveloper Support†ô°ddrw2:°„†ó°d`drw2-ÔˇˇˇˇˇˇKÔ- Z  ffZ°d1drw2 ¿˙ÈˇˇˇˇˇˇK°ñ x°ddrw2:°ddrw2:$°d4drw2:0°öˇÙĆò
  3506. 0(UÔ†ô°ddrw2:°„†ó°d1drw2ÔÊ˙ˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:    °öˇ˝Ä†ò
  3507.     +&    ®†ô°ddrw2:°„†ó°d1drw2Â-¯yˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚Ä%†ò
  3508. (Z\    Macintosh†ô°ddrw2:°„†ó†ç°ddrw2D†É
  3509. IR.°dONLNdn<Å(õZPR 8 - PrGeneral Bug
  3510. °dONLNdÄ<ès*Printing
  3511. °dONLNdõ<ßt* Revised by:°dONLNd,õ≈߲(√„
  3512. March 1988°dONLNd7ß<≥q(œZ Written by:°dONLNdCßÑ≥Û)HScott "ZZ" Zimmerman°dONLNdXß±≥˛(œœ
  3513. November 1987°dONLNdfø<À‚(ÁZUThis technical note documents a bug in the implementation of the PrGeneral procedure °dONLNdªø‚À˛(Áin the°dONLNd¬À<◊˝(ÛZ(LaserWriter driver version 4.0. The bug °dONLNdÍÀ˝◊˛)¡5has to do with the format of the information returned°dONLNd ◊<„F(ˇZ3by the GetRslData opcode. This technical note will °dONLNdS◊F„˛(ˇd"also describe a workaround for the°dONLNdv„<Ôg( Zproblem. X°dONLNd    <€*& One of the opcodes supported by °dONLNdü    €Ì)üthe ,
  3514. Courier°dONLNd£Ì,)    PrGeneral°dONLNd¨    ,˛)?) procedure (Technical Note #128) is named°dONLNd÷<!Ç(>Z
  3515. GetRslData°dONLNd‡Ç"§)F. The °dONLNdʧ!Í)"
  3516. GetRslData°dONLNdÍ"∏)F+ operation initializes a resolution record °dONLNd∏"˛)Œthat is of the°dONLNd*"<.á(JZfollowing form:
  3517.     °dONLNd;:`E+$$TRslRg = RECORD {used in TGetRslBlk}°dONLNdbDÑOù+$
  3518. iMin:°dONLNdhD®O–)$Integer;°dONLNdqDOÂ)H1{0 if printer only supports discrete resolutions}°dONLNd•NÑYù(u¢iMax:°dONLNd´N®Y–)$Integer;°dONLNd¥NY§)H${0 if printer only supports discrete°dONLNd⁄X<c1(Z1                                     resolutions}°dONLNd
  3519. b`mt+$
  3520. END;°dONLNdv`Å∞*TRslRec = RECORD°dONLNd+vÃÅ0)l{used in TGetRslBlk}°dONLNdBÄÑã¢(ߢiXRsl:°dONLNdIÄ®ã–)$Integer;°dONLNdRÄãü)H#{a discrete, physical X resolution}°dONLNdxäÑï¢(±¢iYRsl:°dONLNdä®ï–)$Integer;°dONLNdàäïü)H#{a discrete, physical Y resolution}°dONLNd≠î`üt(ª~END;°dONLNdµ®`≥d*4TGetRslBlk = RECORD {data block for GetRslData call}°dONLNdÏ≤ÑΩ¨+$
  3521. iOpCode:°dONLNdı≤ÃΩÙ)HInteger;°dONLNd˛≤Ωá)H{input; = getRslDataOp}°dONLNdºÑ«¨(„¢iError: °dONLNd!ºÃ«Ù)HInteger;°dONLNd*º«<)H{output}°dONLNd5ΔÑ—∂(Ì¢
  3522. lReserved:°dONLNd@Δ×Ù)HLongInt;°dONLNdIΔ—ë)H{reserved for future use}°dONLNde–Ñ€¨(˜¢iRgType:°dONLNdn–ÀÙ)HInteger;°dONLNdw–€·)H){output; this declaration is for RgType1}°dONLNd£⁄Ѩ(¢XRslRg: °dONLNd¨⁄ÃÂÙ)HTRslRg; °dONLNdµ⁄Â¥)H {output; range of X resolutions}°dONLNdÿ‰ÑÔ¨( ¢YRslRg: °dONLNd·‰ÃÔÙ)HTRslRg; °dONLNd͉ԥ)H {output; range of Y resolutions}°dONLNd
  3523. ÓÑ˘Ë(¢iRslRecCnt: Integer;°dONLNd"Ó˘ï)l!{output; how many RslRecs follow}°dONLNdF¯Ñ±(¢    rgRslRec:°dONLNdP¯Ã)H ARRAY[1..27]°dONLNdbÃ
  3524. È*
  3525. 9OF TRslRec; {output; number used depends on printer type}°dONLNdù `t(3~END;
  3526. °dONLNd¢#</(KZ)The LaserWriter 4.0 implementation has a °dONLNdÀ#/e)…bug that affects the °dONLNd‡"e.è)`YRslRg°dONLNdÊ#è/®)* and °dONLNdÎ"®.“)XRslRg°dONLNdÒ#“/˛)*
  3527.  fields of°dONLNd¸0<<M(XZthe °dONLNd/M;ì)
  3528. TGetRslBlk°dONLNd
  3529. 0ì<d)F/ record. The correct values for the fields are:
  3530.     °dONLNd<HÑS(o¢TGetRslBlk.XRslRg.iMin := 25;°dONLNd\RÑ]*
  3531. TGetRslBlk.XRslRg.iMax := 1500;°dONLNd~\Ñg*
  3532. TGetRslBlk.YRslRg.iMin := 25;°dONLNdûfÑq*
  3533. TGetRslBlk.YRslRg.iMax := 1500;
  3534. °dONLNdæ}<âõ(•ZJUnfortunately, the information returned by the LaserWriter 4.0 version of °dONLNd|õà⁄(•π    PrGeneral°dONLNd}⁄âË)? is: ¡X¡
  3535. (÷ZPR 8 - PrGeneral Bug(÷1) of 2(ÏZM.PR.PrGeneralBugˇ°¿Ù%%DSIDICT:_cv
  3536. currentdict /bu known {bu}if
  3537. userdict /_cv known not{userdict /_cv 30 dict put}if
  3538. _cv begin
  3539. /bdf{bind def}bind def
  3540. currentscreen/cs exch def/ca exch def/cf exch def
  3541. /setcmykcolor where{/setcmykcolor get /cvcmyk exch def}{/cvcmyk{1 sub 4 1 roll 3{3 index add neg dup 0 lt{pop 0}if 3 1 roll}repeat setrgbcolor pop}bdf }ifelse
  3542. /ss{//cf //ca //cs setscreen}bdf
  3543. /stg{ss setgray}bdf
  3544. /strgb{ss setrgbcolor}bdf
  3545. /stcmyk{ss cvcmyk}bdf
  3546. /min1{dup 0 eq{pop 1}if}bdf
  3547. end
  3548. currentdict /bn known {bn}if
  3549. †ø    6◊#ˇ ˇˇˇˇ#◊ 
  3550. IR,Times
  3551. .+6-Macintosh Technical Notes /4/˘,
  3552. Courier
  3553.     °dONLNd`(Ò+HTGetRslBlk.XRslRg.iMin := 25;°dONLNd '`2ˆ*
  3554. TGetRslBlk.XRslRg.iMax := 25; °dONLNdA1`<˚*
  3555. TGetRslBlk.YRslRg.iMin := 1500;°dONLNdc;`F˚*
  3556. TGetRslBlk.YRslRg.iMax := 1500;
  3557. °dONLNdÉR^C(z6:The recommended workaround for this problem is to use the °dONLNdΩQC]â(za
  3558. PrDrvrVers°dONLNd«Râ^ç)F °dONLNd»Rç^Ω)
  3559. function (°dONLNd“RΩ^⁄)0Inside°dONLNdŸ^jI(Ü6    Macintosh°dONLNd‚^Ij")10 II-163) to find out which version of the print °dONLNd^"j⁄)Ÿ&driver you are using. If you are using°dONLNd9jv≤(í6 4.0, modify the resolution data °dONLNdYj≤v⁄)ö=before using it. The following code fragment illustrates this°dONLNdóvÇU(û6 workaround:
  3560.     °dONLNd§é<ôO+$7PROCEDURE CheckRslRecord(VAR theRslRecord: TGetRslBlk);°dONLNd›ò<£U*
  3561. CONST°dONLNd¢`≠µ+$
  3562. BogusDriver = 40;°dONLNd¯¨<∑U(”ZBEGIN°dONLNd∂`¡+$
  3563. &IF PrDrvrVers = BogusDriver THEN BEGIN°dONLNd*¿ÑÀç+$
  3564. 5theRslRecord.XRslRg.iMax := theRslRecord.YRslRg.iMax;°dONLNdc Ñ’ç*
  3565. 5theRslRecord.YRslRg.iMin := theRslRecord.XRslRg.iMin;°dONLNdõ‘`flt(˚~END;°dONLNd£fi<ÈP(ZEND;
  3566. °dONLNd®ı(69When the bug is fixed in a future version of the driver, °dONLNd·ı/(;the °dONLNdÂÙ/ë)CheckRslRecord°dONLNdÛıë⁄)b procedure will°dONLNd
  3567. «()6Yno longer have any effect on the resolution record. This will make sure your application °dONLNd\«
  3568. ⁄()Âgets°dONLNda
  3569. à(56Pthe correct resolution data no matter which version of the driver is being used.°dONLNd≤=IÇ*0Further Reference: h4h˘°dONLNd≈J*V.+
  3570. •°dONLNd«J<Vî)The Print Manager°dONLNdŸV*b.(~H•°dONLNd€V<b‚)Technical Note M.IM.PrGeneral—°dONLNd¸b`nê+$     PrGeneral ¡4¡˘
  3571. (÷62) of 2(÷†PR 8 - PrGeneral Bug+M.PR.PrGeneralBugˇ@◊#ˇ ˇˇˇˇ#◊°d WORDS †å°d WORDR…†Ç 
  3572. /ZÅ#
  3573.     0Ià:µú9"{    ˇˇˇˇˇˇˇˇ#†ƒ°d
  3574. ONLNf˛†å°d1drw2…-·_ġˇˇˇˇˇè°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˙ó@†ò,Times
  3575. .WIQkWIQk+]BNew Technical Notes†ô°ddrw2:°„†ó°d1drw2eÙġˇˇˇˇˇP°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚ÄE¿†ò
  3576. Ä({ïDeveloper Support†ô°ddrw2:°„†ó°d`drw2-ÔˇˇˇˇˇˇKÔ- Z  ffZ°d1drw2 ¿˙ÈˇˇˇˇˇˇK°ñ x°ddrw2:°ddrw2:$°d4drw2:0°öˇÙĆò
  3577. 0(UÔ†ô°ddrw2:°„†ó°d1drw2ÔÊ˙ˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:    °öˇ˝Ä†ò
  3578.     l+&    ®†ô°ddrw2:°„†ó°d1drw2Â-¯yˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚Ä%†ò
  3579. BÄ(Z\    Macintosh†ô°ddrw2:°„†ó†ç°ddrw2D†É°dWORD†ç
  3580. IR.°dONLNdo<Ç_(úZ"PR 9 - Print Dialogs: Adding Items
  3581. °dONLNd#Å<ês*Printing
  3582. °dONLNd-ú<®t* Revised by:°dONLNd:ú≈®˛(ƒ„
  3583. March 1988°dONLNdE®<¥q(–Z Written by:°dONLNdQ®Ñ¥–)HGinger Jernigan°dONLNda®±¥˛(–œ
  3584. November 1986°dONLNdq¥Ñ¿æ(‹¢ Lew Rollins°dONLNd~Ã<ÿÌ(ÙZZThis technical note discusses how to add your own items to the Printing Manager’s dialogs. X°dONLNdŸÒ<˝…*%SWhen the Printing Manager was initially designed, great care was taken to make the °dONLNd,Ò…˝˛(Á interface to°dONLNd9˝<    ª(%ZSthe printer drivers as generic as possible in order to allow applications to print °dONLNdå˝ª    ˛(%Ÿ
  3585. without being°dONLNdö    <f(1Z=device-specific. There are times, however, when this type of °dONLNd◊    f˛(1Ñ!non-specific interface interferes°dONLNd˘<!ï(=Zwith the flexibility °dONLNdï!˛)YKof an application. An application may require additional information before°dONLNdZ!<-û(IZFprinting which is not part of the general Printing Manager interface. °dONLNd†!û-˛(IºThis technical note°dONLNd¥-<9Ö(UZGdescribes a method that an application can use to add its own items to °dONLNd˚-Ö9˛(U£the existing style and job°dONLNd9<Eb(aZdialogs.°dONLNdQ<](*0Before continuing, you need to be aware of some °dONLNdOQ(]˛)Ï-guidelines that will increase your chances of°dONLNd}]<iU(ÖZ>being compatible with the printing architecture in the future:°dONLNdºuNÅR+•°dONLNdæu[Å)
  3586. !Only add items to the dialogs as °dONLNdfluÅ⁄)ß+described in this technical note. Any other°dONLNd Å[çz(©y=methods will decrease your chances of survival in the future.°dONLNdIôN•R(¡l•°dONLNdKô[•≥)
  3587. Do not change the °dONLNd]ô≥•⁄)X=position of any item in the current dialogs. This means don’t°dONLNdõ•[±≤(Õydelete items from °dONLNd≠•≤±⁄)W<the existing item list or add items in the middle. Add items°dONLNdͱ[ΩØ(Ÿyonly at the end°dONLNd˘±ØΩ‚)T
  3588.  of the list.°dONLNd…N’R(Òl•°dONLNd    …[’Q)
  3589. 6Don’t count on an item retaining its current position °dONLNd?…Q’⁄)ˆin the list. If you depend on°dONLNd]’[·¸(˝y$the Draft button being a particular °dONLNdÅ’¸·⁄)°-number in the ImageWriter’s style dialog item°dONLNdØ·[̃(    yDlist, and we change the Draft button’s item number for some reason, °dONLNdÛ·ƒÌ⁄(    ‚your°dONLNd¯Ì[˘$(y)program may no longer function correctly.°dONLNd"NR(-l•°dONLNd$[Í)
  3590. Don’t use more than half the °dONLNdAÍ⁄)è0screen height for your items. Apple reserves the°dONLNdr[í(9yDright to expand the items in the standard print dialogs to fill the °dONLNd∂í⁄(9∞top half of the°dONLNdΔ[)}(Eyscreen.°dONLNdŒ5NAR(]l•°dONLNd–5[A)
  3591. 'If you are adding lots of items to the °dONLNd˜5A⁄)∑&dialogs (which may confuse users), you°dONLNdA[MÌ(iyshould consider having your °dONLNd:AÌM⁄)í/own separate dialog in addition to the existing°dONLNdjM[Y÷(uyPrinting Manager dialogs. ¡X¡
  3592. (÷Z"PR 9 - Print Dialogs: Adding Items(÷ˇ1) of 13(ÏZM.PR.PrintDialogsAddingItemsˇ°¿Ù%%DSIDICT:_cv
  3593. currentdict /bu known {bu}if
  3594. userdict /_cv known not{userdict /_cv 30 dict put}if
  3595. _cv begin
  3596. /bdf{bind def}bind def
  3597. currentscreen/cs exch def/ca exch def/cf exch def
  3598. /setcmykcolor where{/setcmykcolor get /cvcmyk exch def}{/cvcmyk{1 sub 4 1 roll 3{3 index add neg dup 0 lt{pop 0}if 3 1 roll}repeat setrgbcolor pop}bdf }ifelse
  3599. /ss{//cf //ca //cs setscreen}bdf
  3600. /stg{ss setgray}bdf
  3601. /strgb{ss setrgbcolor}bdf
  3602. /stcmyk{ss cvcmyk}bdf
  3603. /min1{dup 0 eq{pop 1}if}bdf
  3604. end
  3605. currentdict /bn known {bn}if
  3606. †øå◊#ˇ ˇˇˇˇ#◊ 
  3607. IR,Times
  3608. .+6-Macintosh Technical Notes /4/˘
  3609. °dONLNd,Z*    The Heart
  3610. °dONLNd
  3611. 8Dï*Before we talk about how °dONLNd#8ïD⁄)}Dthe dialogs work, you need to know this: at the heart of the printer°dONLNdhDP~(l6Ndialogs is a little-known data structure partially documented in the MacPrint °dONLNd∂D~P⁄(lúinterface file. It’s a°dONLNdÕQ]W(y6record called ,
  3612. Courier°dONLNd€PW\Å)?TPrDlg°dONLNd·QÅ]Ê)* and it looks like this:
  3613.     °dONLNd˚i<tc(êZ;TPrDlg = RECORD   {Print Dialog: The Dialog Stream object.}°dONLNd8s<~"*
  3614. .   dlg       : DialogRecord;   {dialog window}°dONLNdh}<à*
  3615. -   pFltrProc : ProcPtr;        {filter proc.}°dONLNdóá<íJ*
  3616. 6   pItemProc : ProcPtr;        {item evaluating proc.}°dONLNdœë<úE*
  3617. 5   hPrintUsr : THPrint;        {user’s print record.}°dONLNdõ<¶Ø*
  3618.    fDoIt     : BOOLEAN;°dONLNd•<∞Ø*
  3619.    fDone     : BOOLEAN;°dONLNd8Ø<∫m*
  3620. =   lUser1    : LONGINT;        {four longs reserved by Apple}°dONLNdwπ<ƒØ*
  3621.    lUser2    : LONGINT;°dONLNdê√<ŒØ*
  3622.    lUser3    : LONGINT;°dONLNd©Õ<ÿØ*
  3623.    lUser4    : LONGINT;°dONLNd¬◊<‚Ü*
  3624. B   iNumFst   : INTEGER;        {numeric edit items for std filter}°dONLNd·<ÏØ*
  3625.    iNumLst   : INTEGER;°dONLNd%Î<ˆw*
  3626. ?{... plus more stuff needed by the particular printing dialog.}°dONLNdfı<P*
  3627. END;°dONLNdlˇ<
  3628. ,*
  3629. 0TPPrDlg = ^TPrDlg;             {== a dialog ptr}
  3630. °dONLNdù"L(>6CAll of the information pertaining to a print dialog is kept in the °dONLNd‡L!v(>jTPrDlg°dONLNdÊv"⁄)* record. This record°dONLNd˚".(J67will be referred to frequently in the discussion below.
  3631. °dONLNd3FUØ*'How the Dialogs Work
  3632. °dONLNdHbn¢*When your application calls °dONLNdda¢mÔ)ä PrStlDialog°dONLNdobÔn)M and °dONLNdtamU) PrJobDialog°dONLNdbUn⁄)M, the printer driver actually°dONLNdùo{z(ó6calls a routine called °dONLNd¥nzzπ)b    PrDlgMain°dONLNdΩoπ{k)?'. This function is declared as follows:
  3633. °dONLNdÊá<ì¬(ØZAFUNCTION PrDlgMain (hprint: THPrint; pDlgInit: ProcPtr): BOOLEAN;
  3634. °dONLNd(û™W(«6    PrDlgMain°dONLNd1üW´ô)? first calls the °dONLNdBûô™—)BpDlgInit°dONLNdJü—´ú)8. routine to set up the appropriate dialog (in °dONLNdxûú™±)ÀDlg°dONLNd{ü±´⁄)    ), dialog°dONLNdÖ¨∏3(‘6hook °dONLNdä´3∑Ä) (pItemProc)°dONLNdï¨Ä∏Ï)M and dialog event filter °dONLNdÆ´Ï∑G)l
  3635. (pFilterProc)°dONLNdª¨G∏g)[ in the °dONLNd√´g∑ë) TPrDlg°dONLNd…¨ë∏î)* °dONLNd ¨î∏⁄)
  3636. record (shown°dONLNdÿπ≈ü(·6above). For the job dialog, °dONLNdÙπü≈Í)áthe address of °dONLNd∏̓))K    PrJobInit°dONLNd π)≈n)? is passed to °dONLNd∏nƒ≠)E    PrDlgMain°dONLNd#π≠≈⁄)?    . For the°dONLNd-Δ“ö(Ó6style dialog, the address of °dONLNdJ≈ö—Ÿ)Ç    PrStlInit°dONLNdSΔŸ“≈)?3 is passed. These routines are declared as follows:
  3637.     °dONLNdàfi<È"(Z.FUNCTION PrJobInit (hPrint: THPrint): TPPrDlg;°dONLNd∏Ë<Û"*
  3638. .FUNCTION PrStlInit (hPrint: THPrint): TPPrDlg;
  3639. °dONLNdÁˇ ‡('6-After the initialization routine sets up the °dONLNd˛‡
  3640. 
  3641. )»TPrDlg°dONLNdˇ
  3642.  6)*     record, °dONLNd#˛6
  3643. u),    PrDlgMain°dONLNd,ˇu î)? calls °dONLNd3˛î
  3644. ⁄)
  3645. ShowWindow°dONLNd> ‚(46-(the window is initially invisible), then it °dONLNdk ‚¸) calls °dONLNdq ¸I) ModalDialog°dONLNd| I⁄)M, using the dialog event filter°dONLNdú%r(A6pointed to by the °dONLNdÆr$±)Z    pFltrProc°dONLNd∑±%⁄)?: field. When an item is hit, the routine pointed to by the°dONLNdÚ%1W(N6    pItemProc°dONLNd˚&W2y)?? field is called and the items are handled appropriately. When °dONLNd:&y2⁄(Nóthe OK button is hit°dONLNdO2>)(Z6:(this includes pressing Return or Enter) the print record °dONLNdâ2)>⁄(ZG%is validated. The print record is not°dONLNdØ>Jø(f6&validated if the Cancel button is hit.
  3646. °dONLNd÷bq⁄*'How to Add Your Own Items
  3647. °dONLNd~ä*4To modify the print dialogs, you need to change the °dONLNd    $}â9)˜TPrDlg°dONLNd    *~9äè)* record before the °dONLNd    =~èä⁄)Vdialog is drawn°dONLNd    Mäñ(≤61on the screen. You can add your own items to the °dONLNd    ~äñ⁄(≤9'item list, replace the addresses of the ¡4¡˘
  3648. (÷62) of 13(÷i"PR 9 - Print Dialogs: Adding Items+M.PR.PrintDialogsAddingItemsˇÆ◊#ˇ ˇˇˇˇ#◊ 
  3649. IR,Times
  3650. .+Z-Developer Support Center(-Ï
  3651. March 1988 /X/
  3652. °dONLNd<)“(EZstandard dialog hook and event °dONLNd“)˛)ñ?filter with the addresses of your own routines and then let the°dONLNd_)<5Ù(QZ&dialog code continue on its merry way.,
  3653. Courier°dONLNdáA<Mf*TPrDlg°dONLNdçBfN$)*( record for you and return a pointer to °dONLNdµB$Nì)æthat record. Then call °dONLNdÃAìM“)o    PrDlgMain°dONLNd’B“N˛)?
  3654.  directly,°dONLNd‡N<ZÉ(vZpassing in the °dONLNdÔNÉZ˛)GNaddress of your own initialization function. The example code’s initialization°dONLNd>Z<f›(ÇZ[function adds items to the dialog item list, saves the address of the standard dialog hook °dONLNdôZ›f˛(Ç˚(in our°dONLNd°g<sÑ(èZglobal variable °dONLNd±fÑr—)H prPItemProc°dONLNdºg—s{)M%) and puts the address of our dialog °dONLNd·g{sø)™hook into the °dONLNdÔfør˛)D    pItemProc°dONLNd˘t<Äu(úZ
  3655. field of the °dONLNdsuü)9TPrDlg°dONLNd tüÄo)*+ record. Please note that your dialog hook °dONLNd7toÄä)–must°dONLNd;täÄ¥)
  3656.  call the °dONLNdEt¥Ä˛)*standard dialog°dONLNdUÄ<å"(®Z2hook to handle all of the standard dialog’s items.°dONLNdàò<§[*Note:°dONLNdçò[§À) If you wish to have an °dONLNd•òÀ§⁄)p9event filter, handle it the same way that you do a dialog°dONLNdfl§`∞|(Ã~hook.°dONLNdº<»~(‰ZBNow, here is an example (written in MPW Pascal) that modifies the °dONLNd'º~»˛(‰újob dialog. The same code°dONLNdA»<‘ò(Zworks for the style °dONLNdU»ò‘˛)\Ldialog if you globally replace ‘Job’ with ‘Stl’. Also included is a function°dONLNd¢’<·@(˝Z(°dONLNd£‘@‡Ü)
  3657. AppendDITL°dONLNd≠’Ü·)F) provided by Lew Rollins °dONLNd«’·˛)Ä7(originally written in C, translated for this technical°dONLNdˇ·<ÌH(    Z3note to MPW Pascal) which demonstrates a method of °dONLNd2·HÌ˛(    f&adding items to the item list, placing°dONLNdYÌ<˘°(ZJthem in an appropriate place, and expanding the dialog window’s rectangle.
  3658. °dONLNd§< )*'The MPW Pascal Example Program
  3659.     °dONLNd√,<7™*PROGRAM ModifyDialogs;°dONLNd€@`Kt+$USES°dONLNd‚JÑUË+$
  3660. {$LOAD PasDump.dump}°dONLNd˘TÑ_ç*
  3661. 5MemTypes,QuickDraw,OSIntf,ToolIntf,PackIntf,MacPrint;°dONLNd0h`sy(è~CONST°dONLNd8rÑ}¢+$
  3662. MyDITL°dONLNd@rÃ}Ô)H = 256;°dONLNdJ|Ñáfi(£¢MyDFirstBox  = 1; °dONLNd^|á√)ê# {Item number of first box in DITL}°dONLNdÑÜÑëŸ(≠¢MyDSecondBox = 2;°dONLNdóö`•o(¡~VAR°dONLNdù§ÑØÚ+$
  3663. PrtJobDialog: TPPrDlg;°dONLNd¥§Øë)ê{ pointer to job dialog }°dONLNd–ÆÑπ±(’¢    hPrintRec°dONLNd⁄ÆÃπ˛)H
  3664. : THPrint;°dONLNdÂÆπñ)H{ Handle to print record }°dONLNd∏Ñ√œ(fl¢FirstBoxValue, °dONLNd∏√π)ê!{ value of first additional box }°dONLNd7¬ÑÕ(È¢SecondBoxValue: Integer; °dONLNdQ¬Õ™)ê{ value of second addtl. box }°dONLNdrÃÑ◊¿(Û¢ prFirstItem,°dONLNdÅÃ◊†)ê{ save our first item here }°dONLNd†÷Ñ·Ú(˝¢prPItemProc : LongInt;°dONLNd∑÷·√)ê#{ need to store old itemProc here }°dONLNd›‡Ñα(¢    itemType °dONLNdÁ‡Ãβ)H
  3665. : Integer;°dONLNdڇλ)H${ need for GetDItem/SetDItem calls }°dONLNdÍÑı¢(¢itemH °dONLNd!ÍÃı˘)H    : Handle;°dONLNd-ÙÑˇß(¢itemBox°dONLNd6Ùˇ)l: Rect;°dONLNd@˛Ñ    ì(%¢err°dONLNdF˛    )l: OSErr;°dONLNdO<Æ(/ZJ{------------------------------------------------------------------------}°dONLNdõ`'ƒ+$PROCEDURE _DataInit;°dONLNd≤&Ñ1±+$
  3666.     EXTERNAL;°dONLNdº:<EÆ(aZJ{------------------------------------------------------------------------}°dONLNdN`Y•+$APROCEDURE CallItemHandler(theDialog: DialogPtr; theItem: Integer;°dONLNdOXcJ+ê
  3667. theProc: LongInt);°dONLNddbÑm¿(⢠INLINE $205F°dONLNdsbmn)ê{ MOVE.L (A7)+,A0}°dONLNdàlÑwß(ì¢,$4E90;°dONLNdílwP)ê { JSR (A0) }°dONLNdüÄ<ãö(ßZF{ this code pops off theProc and then does a JSR to it, which puts the°dONLNdÊä<ï*
  3668. $ real return address on the stack. } ¡X¡
  3669. *%"PR 9 - Print Dialogs: Adding Items(÷ˇ3) of 13(ÏZM.PR.PrintDialogsAdding Itemsˇ4◊#ˇ ˇˇˇˇ#◊ 
  3670. IR,Times
  3671. .+6-Macintosh Technical Notes /4/˘,
  3672. Courier
  3673.     °dONLNd'2ä*!J{------------------------------------------------------------------------}°dONLNdL;<Fü+$GFUNCTION AppendDITL(theDialog: DialogPtr; theDITLID: Integer): Integer;°dONLNdïE<Pã*
  3674. C{ version 0.1 9/11/86 Lew Rollins of Human-Systems Interface Group}°dONLNd⁄O<Z,*
  3675. 0{ this routine still needs some error checking }°dONLNd cn?(ä6;{ This routine appends all of the items of a specified DITL°dONLNdGmxÄ*
  3676. Honto the end of a specified DLOG — We don’t even need to know the format°dONLNdêwÇY*
  3677.  
  3678. of the DLOG }°dONLNdûãñ≥*{ this will be done in 3 steps:°dONLNdæï†]*
  3679. A 1. append the items of the specified DITL onto the existing DLOG°dONLNdü™
  3680. *
  3681. 1 2. expand the original dialog window as required°dONLNd2©¥5*
  3682. 9 3. return the adjusted number of the first new user item°dONLNdl≥æ*
  3683. }°dONLNdoΩ<»P+$
  3684. TYPE°dONLNdv«`“µ+$
  3685. DITLItem = RECORD°dONLNdà«Ã“D)l{ First, a single item }°dONLNd§—Ñ‹e(¯¢-{ Handle or procedure pointer for this item }°dONLNd÷€®Ê¯+$
  3686. itmHndl: Handle;°dONLNdÍÂÑ3( ¢#{ Display rectangle for this item }°dONLNdÔ®˙Ó+$
  3687. itmRect: Rect;°dONLNd%˘Ñ8( ¢${ Item type for this item — 1 byte }°dONLNdN® +$
  3688. itmType: SignedByte;°dONLNdf
  3689. ј(4¢{ Length byte of data }°dONLNdÇ®"\+$
  3690. $itmData: ARRAY [0..0] OF SignedByte;°dONLNd©!`,t(H~END;°dONLNdÆ!Ñ,∂)$
  3691. {DITLItem}°dONLNdª+`6ç(R~    pDITLItem°dONLNd≈+®6È)H
  3692.  = ^DITLItem;°dONLNd’5`@ç(\~    hDITLItem°dONLNdfl5®@Ó)H = ^pDITLItem;°dONLNdI`Tµ(p~ItemList = RECORD°dONLNdIÃTS)l{ Then, the list of items }°dONLNd!SÑ^(z¢ { Number of items minus 1 }°dONLNdB]®h+$
  3693. dlgMaxIndex: Integer;°dONLNd[gÑrfi(é¢{ Array of items }°dONLNdrq®|\+$
  3694. $DITLItems: ARRAY [0..0] OF DITLItem;°dONLNdô{<ÜP(¢ZEND;°dONLNdû{`Üó)$  {ItemList}°dONLNd¨Ö`êç*
  3695.     pItemList°dONLNd∂Ö®êÈ)H
  3696.  = ^ItemList;°dONLNdΔè`öç(∂~    hItemList°dONLNd–è®öÓ)H = ^pItemList;°dONLNd·£`Æ~( ~IntPtr°dONLNdÈ£®Ɖ)H  = ^Integer;°dONLNd˜∑<¬K(fiZVAR°dONLNd˝¡`ô+$
  3697. offset : Point;°dONLNd
  3698. ¡Ãã)l+{ Used to offset rectangles appended items}°dONLNd;À`÷¶(Ú~maxRect: Rect;°dONLNdJÀÃ÷û)l*{ Used to track increases in window size }°dONLNdw’`‡ø(¸~hDITL : hItemList; °dONLNdã’Çq)l!{ Handle to DITL being appended }°dONLNdØfl`Í∫(~pItem : pDITLItem;°dONLNd¬flÃÍû)l*{ Pointer to current item being appended }°dONLNdÔÈ`Ù∫(~hItems: hItemList;°dONLNdÈÃÙb)l{ Handle to DLOG’s item list }°dONLNd#Û`˛ø(~firstItem: Integer;°dONLNd7ÛÃ˛û)l*{ offset to first item is to be appended }°dONLNdd˝`∫($~newItems: Integer;°dONLNdw˝Ã:)l{ Count of new items }°dONLNdê`ø(.~dataSize : Integer;°dONLNd§Ãq)l!{ Size of data for current item }°dONLNd»`°(8~
  3699. i : Integer; °dONLNd◊Ã!)l{ Working index }°dONLNdÎ`&ó(B~ USB: RECORD°dONLNd¯Ã&î)l({ needed because itmData[0] is unsigned}°dONLNd$%Ñ0œ(L¢CASE Integer OF°dONLNd8/®:≤+$
  3700. 1:°dONLNd@9ÃDä+$
  3701. &(SBArray: ARRAY [0..1] OF SignedByte);°dONLNdkC®N≤(jΔ2:°dONLNdsMÃX+$
  3702. (Int: Integer);°dONLNdÖW`bt(~~END;°dONLNdäWÑb¢)$ {USB}°dONLNdík<vZ(íZBEGIN °dONLNdökÑv¿)H {AppendDITL}°dONLNdßuÄ(ú6{
  3703. °dONLNd©ãê* Using the original DLOG ¡4¡˘
  3704. */4) of 13(÷i"PR 9 - Print Dialogs: Adding Items+M.PR.PrintDialogsAddingItemsˇ
  3705. `◊#ˇ ˇˇˇˇ#◊ 
  3706. IR,Times
  3707. .+Z-Developer Support Center(-Ï
  3708. March 1988 /X/
  3709. °dONLNd<)¸(EZ& 1. Remember the original window Size.°dONLNd')<5h* A 2. Set the offset Point to be the bottom of the original window.°dONLNdi5<AC* 8 3. Subtract 5 pixels from bottom and right, to be added°dONLNd¢A<MF* 8      back later after we have possibly expanded window.°dONLNd€M<Y * - 4. Get working Handle to original item list.°dONLNd    Y<eN* = 5. Calculate our first item number to be returned to caller.°dONLNdGe<q* - 6. Get locked Handle to DITL to be appended.°dONLNduq<}ÿ* ! 7. Calculate count of new items.,
  3710. Courier
  3711.     °dONLNdó}<àA* }°dONLNdõáÑíó+H
  3712. 7maxRect := DialogPeek(theDialog)^.window.port.portRect;°dONLNd’ëÑú *
  3713. offset.v := maxRect.bottom;°dONLNdÛõѶ *
  3714. offset.h := 0;°dONLNd•Ñ∞=*
  3715. %maxRect.bottom := maxRect.bottom - 5;°dONLNd,ØÑ∫3*
  3716. #maxRect.right := maxRect.right - 5;°dONLNdRπу~*
  3717. 2hItems := hItemList(DialogPeek(theDialog)^.items);°dONLNdá√ÑŒB*
  3718. &firstItem := hItems^^.dlgMaxIndex + 2;°dONLNd∞ÕÑÿ~*
  3719. 2hDITL := hItemList(GetResource('DITL',theDITLID));°dONLNdÂ◊Ñ‚Ì*
  3720. HLock(Handle(hDITL));°dONLNd˝·ÑÏ8*
  3721. $newItems := hDITL^^.dlgMaxIndex + 1;°dONLNd"Î<ˆA(Z{
  3722. °dONLNd$ı<É*  For each item,°dONLNd4<
  3723. >* 8  1. Offset the rectangle to follow the original window.°dONLNdm
  3724. <(* 2  2. Make the original window larger if necessary.°dONLNd†<%¸* +  3. fill in item Handle according to type.
  3725.     °dONLNdÃ%<0A* }°dONLNd–9ÑD+HpItem := @hDITL^^.DITLItems;°dONLNdÔCÑN*
  3726. FOR i := 1 TO newItems DO BEGIN°dONLNdM®Xâ+$
  3727. -OffsetRect(pItem^.itmRect,offset.h,offset.v);°dONLNdCW®bz*
  3728. *UnionRect(pItem^.itmRect,maxRect,maxRect);°dONLNdqa®lÈ*
  3729.  
  3730. USB.Int := 0;°dONLNdÄaln)l {zero things out}°dONLNdñk®v\(íΔ$USB.SBArray[1] := pItem^.itmData[0];°dONLNdæ®ä¢*2{ Strip enable bit since it doesn’t matter here. }°dONLNdÙâ®îÓ*
  3731. WITH pItem^ DO°dONLNdìÃûI+$
  3732. CASE BAND(itmType,$7F) OF°dONLNd&ù®Æ+$
  3733. &{ Can’t do anything with user items. }°dONLNdRß≤*
  3734.     userItem:°dONLNdd±º_+$
  3735. itmHndl := NIL;°dONLNdzªΔ™*
  3736. ctrlItem + btnCtrl,ctrlItem + °dONLNdü≈–æ*
  3737. "chkCtrl,ctrlItem + radCtrl:{build °dONLNd»œ⁄<*
  3738. Control)°dONLNdÿŸ8‰j+$
  3739.  
  3740. itmHndl :=°dONLNd„„<Ó(
  3741. Z*Handle(NewControl(theDialog, { theWindow }°dONLNd˜m+¥  itmRect, { boundsRect }°dONLNdH §*$  StringPtr(@itmData[0])^, { title }°dONLNd}*O*  true, { visible }°dONLNd°3>|*  0,0,1, { value, min, max }°dONLNdŒGRã*  BAND(itmType,$03), { procID }°dONLNd˛[fE*  0)); { refCon }°dONLNdep‹+$
  3742. (ctrlItem + resCtrl: BEGIN { Get resource°dONLNdEoz_*
  3743. based Control }°dONLNd\y8Ñj+$
  3744.  
  3745. itmHndl :=°dONLNdgÉ<éT(™Z8Handle(GetNewControl(IntPtr(@itmData[1])^, { controlID } ¡X¡
  3746. *,"PR 9 - Print Dialogs: Adding Items(÷ˇ5) of 13(ÏZM.PR.PrintDialogsAdding Itemsˇ
  3747. ê◊#ˇ ˇˇˇˇ#◊ 
  3748. IR,Times
  3749. .+6-Macintosh Technical Notes /4/˘,
  3750. Courier
  3751.     °dONLNd'2|+ÿ!  theDialog)); { theWindow }°dONLNd$;<FÜ(bZBControlHandle(itmHndl)^^.contrlRect := itmRect; {give it the right°dONLNd~Y<ds*  rectangle}°dONLNdëcn•+ÿ
  3752. {An actionProc for a Control °dONLNdµmxñ*
  3753.  should be installed here}°dONLNd÷wÇ(ûEND;°dONLNd›w\Ç∂)l {Case ctrlItem + °dONLNd¯Å\åé*
  3754.  
  3755.   resCtrl}°dONLNd    ãñ∏(≤(statText,editText: { Both need Handle to°dONLNd:ï8†´+H
  3756.        a copy of their °dONLNdZü\™+$
  3757. text. }°dONLNdi©¥™(–2err := PtrToHand(@itmData[1], °dONLNdé≥æi*
  3758. ( Start of data }°dONLNd¨«<“(ÓZ$  itmHndl, { Address of new Handle }°dONLNd›€<Ê“*  USB.Int); { Length of text }°dONLNdÂ+¥
  3759.     iconItem:°dONLNd Â8´)H { Icon needs resource °dONLNd+Ô8˙t*
  3760.    Handle. }°dONLNd?˘i( 2pItem^.itmHndl :=°dONLNdQ˘(*6-GetIcon(IntPtr(@itmData[1])^); { ICON resID }°dONLNdÖ
  3761. +ÿ
  3762.     picItem: °dONLNdè
  3763. 8∫)H { Picture needs resource °dONLNd±8"t*
  3764.    Handle. }°dONLNd≈!,i(H2pItem^.itmHndl :=°dONLNd◊+6!(R65Handle(GetPicture(IntPtr(@itmData[1])^));{PICT resID}°dONLNd5@+ÿ
  3765.     OTHERWISE°dONLNd$?J_+$
  3766. itmHndl := NIL;°dONLNd9IÃT‡(pÍEND;°dONLNdAI\T)ê {Case}°dONLNdM]®h\(ÑΔ$dataSize := BAND(USB.Int + 1,$FFFE);°dONLNdvg®r**
  3767. {now advance to next item}°dONLNdïq®|¢*
  3768. 2pItem := pDITLItem(Ptr(ord4(@pItem^) + dataSize + °dONLNdÀ{®Ü*
  3769. sizeof(DITLItem)));°dONLNd‚ÖÑêò(¨¢END;°dONLNdÏÖ\êz)ÿ {for}°dONLNdˆèÑöŸ(∂¢err := PtrAndHand°dONLNdô§(¿6 °dONLNd £<ÆÅ+$
  3770. A(@hDITL^^.DITLItems,Handle(hItems),GetHandleSize(Handle(hDITL)));°dONLNdQ≠Ñ∏ú+H
  3771. 8hItems^^.dlgMaxIndex := hItems^^.dlgMaxIndex + newItems;°dONLNdç∑Ѭ˜*
  3772. HUnlock(Handle(hDITL));°dONLNd®¡ÑÃ*
  3773. ReleaseResource(Handle(hDITL));°dONLNdÀÀÑ÷=*
  3774. %maxRect.bottom := maxRect.bottom + 5;°dONLNdْч3*
  3775. #maxRect.right := maxRect.right + 5;°dONLNdflÑÍú*
  3776. 8SizeWindow(theDialog,maxRect.right,maxRect.bottom,true);°dONLNdWÈÑÙ¸*
  3777. AppendDITL := firstItem;°dONLNdrÛ`˛t(~END;°dONLNd}Û\˛ù)¸
  3778.  {AppendDITL}°dONLNdå<Æ(.ZJ{------------------------------------------------------------------------}°dONLNdÿ<&h*<PROCEDURE MyJobItems(theDialog: DialogPtr; itemNo: Integer);°dONLNd%0"(L6 {°dONLNd/:X*
  3779. @ This routine replaces the routine in the pItemProc field in the°dONLNd[9<D+$
  3780. (TPPrDlg record.  The steps it takes are:°dONLNdÖC<NΩ*
  3781. M1. Check to see if the item hit was one of ours. This is done by “localizing”°dONLNd’M`Xå+$
  3782. <  the number, assuming that our items are numbered from 0..n°dONLNdW<bm(~Z=2. If it’s one of ours  then case it and Handle appropriately°dONLNdRa<lY*
  3783. 93. If it isn’t one of ours then call the old item handler°dONLNdåkv"(í6 } ¡4¡˘
  3784. *D6) of 13(÷i"PR 9 - Print Dialogs: Adding Items+M.PR.PrintDialogsAddingItemsˇ4◊#ˇ ˇˇˇˇ#◊ 
  3785. IR,Times
  3786. .+Z-Developer Support Center(-Ï
  3787. March 1988 /X/,
  3788. Courier
  3789.     °dONLNdÑ(ì(D¢VAR°dONLNd'®2*+$
  3790. MyItem,firstItem: Integer;°dONLNd%1®<Δ*
  3791. thePt °dONLNd-1<)H: Point;°dONLNd9;®FÀ(bΔthePart°dONLNdB;FF)l
  3792. : Integer;°dONLNdPE®P’(lΔ    theValue °dONLNdZEP")H
  3793. : Integer;°dONLNdhO®Z’(vΔ    debugPart°dONLNdrOZ")H
  3794. : Integer;°dONLNdcÑn¢(ä¢BEGIN °dONLNdãc\nù)ÿ
  3795.  {MyJobItems}°dONLNdúm®xª(îΔ7firstItem := prFirstItem; { remember, we saved this in °dONLNd⁄wÇ}+l
  3796.        myJobDlgInit }°dONLNdÛÅ®åfi(®Δ>MyItem := itemNo - firstItem + 1; { “localize” current item No°dONLNd2ã<ñA(≤Z}°dONLNd7ﮆfi+l
  3797. >IF MyItem > 0 THEN BEGIN { if localized item > 0, it’s one of °dONLNd{ü™P+l
  3798.       ours }°dONLNdå©Ã¥è(–Í'{ find out which of our items was hit }°dONLNd∏≥ÃæΔ*
  3799. 2GetDItem(theDialog,itemNo,itemType,itemH,itemBox);°dONLNdÔΩû*
  3800. CASE MyItem OF°dONLNd«“J+$
  3801. MyDFirstBox: BEGIN°dONLNd—‹»+$
  3802. ${ invert value of FirstBoxValue and °dONLNdF€ÊZ*
  3803.    redraw it }°dONLNd[Â√*
  3804. #FirstBoxValue := 1 - FirstBoxValue;°dONLNdÖ˘`P( ~0SetCtlValue(ControlHandle(itemH),FirstBoxValue);°dONLNdª+ê
  3805. END;°dONLNd√Äfl)ê {case MyDFirstBox}°dONLNd‹
  3806. O(4MyDSecondBox: BEGIN°dONLNdˆ"Õ+$
  3807. %{ invert value of SecondBoxValue and °dONLNd!!,U*
  3808.  
  3809.   redraw it }°dONLNd5+6Õ*
  3810. %SecondBoxValue := 1 - SecondBoxValue;°dONLNda?`JU(f~1SetCtlValue(ControlHandle(itemH),SecondBoxValue);°dONLNdòIT+ê
  3811. END;°dONLNd†IÄT£)ê {case °dONLNd±SÄ^À*
  3812.   MyDSecondBox}°dONLNdΔ]h(Ñ    OTHERWISE°dONLNd÷gr2+$
  3813. Debug;°dONLNdfig\rfi)H { OH OH — We got an item °dONLNdˇq8|ƒ(òV          we didn’t expect }°dONLNd {Ã܇(¢ÍEND;°dONLNd){ÄÜ£)¥ {Case}°dONLNd4Ö®ê∑(¨ΔEND°dONLNd=ÖÄê⁄)ÿ { if MyItem > 0 }°dONLNdSè®ö¡(∂ΔELSE °dONLNd\è8ö‚)ê" { chain to standard item handler,°dONLNdÜô8§∫*
  3814.    whose address is saved °dONLNd≤≠∏d(‘2in prPItemProc }°dONLNd«∑ì≤(fiÍ.CallItemHandler(theDialog,itemNo,prPItemProc);°dONLNd¯¡ÑÃò(Ë¢END;°dONLNd¡ÄÃÀ)¸ { MyJobItems }°dONLNd’`‡“(¸~J{------------------------------------------------------------------------}°dONLNd`È`ÙP*0FUNCTION MyJobDlgInit(hPrint: THPrint): TPPrDlg;°dONLNdëÛ<˛A(Z{°dONLNdì˝<ö*
  3815. F This routine appends items to the standard job dialog and sets up the°dONLNd⁄<1*
  3816. 1 user fields of the printing dialog record TPRDlg°dONLNd <    *
  3817. ) This routine will be called by PrDlgMain°dONLNd6<&™*
  3818.  This is what it does:°dONLNdM%<0O*
  3819. 7 1. First call PrJobInit to fill in the TPPrDlg record.°dONLNdÖ/<:Ü*
  3820. B 2. Append our items onto the old DITL. Set them up appropriately.°dONLNd»9<Dö*
  3821. F 3. Save the address of the old item handler and replace it with ours.°dONLNdC<N    *
  3822. ) 4. Return the Fixed dialog to PrDlgMain.°dONLNd9M<XF*
  3823.  }°dONLNd>aÑlì+HVAR°dONLNdEk®v’+$
  3824.     firstItem°dONLNdOkv§)H$: Integer; { first new item number }°dONLNdvÑä¢(¶¢BEGIN °dONLNdÇ\äß)ÿ {MyJobDlgInit}°dONLNdïâ®î¿(∞Δ8firstItem := AppendDITL(DialogPtr(PrtJobDialog),MyDITL); ¡X¡
  3825. (÷Z"PR 9 - Print Dialogs: Adding Items(÷ˇ7) of 13(ÏZM.PR.PrintDialogsAdding Itemsˇ ‹◊#ˇ ˇˇˇˇ#◊ 
  3826. IR,Times
  3827. .+6-Macintosh Technical Notes /4/˘,
  3828. Courier
  3829.     °dONLNd'Ñ2ó+l!7prFirstItem := firstItem; { save this so MyJobItems can°dONLNd>1<@+l
  3830.        find it }°dONLNdREÑPç(l¢5{ now we’ll set up our DITL items — The "First Box" }°dONLNdãY<dã(ÄZCGetDItem(DialogPtr(PrtJobDialog),firstItem,itemType,itemH,itemBox);°dONLNd“cÑnt+H
  3831. 0SetCtlValue(ControlHandle(itemH),FirstBoxValue);°dONLNdwÑÇ∫*>{ now we’ll set up the second of our DITL items — The "Second °dONLNdGÅÑå¨*
  3832.   Box" }°dONLNdSãÑñe*
  3833. -GetDItem(DialogPtr(PrtJobDialog),firstItem + °dONLNdÖïц*
  3834. 1,itemType,itemH,itemBox);°dONLNd£üÑ™y*
  3835. 1SetCtlValue(ControlHandle(itemH),SecondBoxValue);°dONLNd’≥æÖ(⁄6I{ Now comes the part where we patch in our item handler.  We have to save°dONLNdΩ»{*
  3836. G the old item handler address, so we can call it if one of the standard°dONLNdg«“
  3837. *
  3838. 1 items is hit, and put our item handler’s address°dONLNdô—‹Â*
  3839. ) in pItemProc field of the TPrDlg struct}°dONLNdΔÂÑt+l0prPItemProc := LongInt(PrtJobDialog^.pItemProc);°dONLNd˙˘Ñ∫*>{ Now we’ll tell the modal item handler where our routine is }°dONLNd<Ñt*
  3840. 0PrtJobDialog^.pItemProc := ProcPtr(@MyJobItems);°dONLNdpÑ"´*;{ PrDlgMain expects a pointer to the modified dialog to be °dONLNdÆ!Ñ,‘*
  3841.   returned.... }°dONLNd¬+Ñ6*
  3842. MyJobDlgInit := PrtJobDialog;°dONLNd‚?`Jt(f~END;°dONLNdÌ?\Jß)¸ {myJobDlgInit}°dONLNd˛S<^Æ(zZJ{------------------------------------------------------------------------}°dONLNdJg<r™*FUNCTION Print: OSErr;°dONLNdc{`Üo+$VAR°dONLNdjÖÑêò+$
  3843. bool°dONLNdqÖê")l
  3844. : BOOLEAN;°dONLNd~ô`§~(¿~BEGIN °dONLNdäô8§`)ÿ {Print}°dONLNdñ£ÑÆt( ¢0hPrintRec := THPrint(NewHandle(sizeof(TPrint)));°dONLNd ≠Ñ∏¸*
  3845. PrintDefault(hPrintRec);°dONLNdÊ∑Ѭ*
  3846. bool := PrValidate(hPrintRec);°dONLNd¡ÑÃ$*
  3847.  IF (PrError <> noErr) THEN BEGIN°dONLNd-À®÷˝+$
  3848. Print := PrError;°dONLNdC’®‡‰*
  3849. Exit(Print);°dONLNdSflÑÍò(¢END;°dONLNd]fl\Íu)ÿ {If}°dONLNdfÛÑ˛µ(¢={ call PrJobInit to get pointer to the invisible job dialog }°dONLNdß˝Ñ=*
  3850. %PrtJobDialog := PrJobInit(hPrintRec);°dONLNd–Ñ$*
  3851.  IF (PrError <> noErr) THEN BEGIN°dONLNdı®˝+$
  3852. Print := PrError;°dONLNd ®&‰*
  3853. Exit(Print);°dONLNd%Ñ0ò(L¢END;°dONLNd%%\0u)ÿ {If}°dONLNd+9DÃ(`6$ {Here’s the line that does it all!}°dONLNdSCÑNí+l
  3854. 6IF NOT (PrDlgMain(hPrintRec,@MyJobDlgInit)) THEN BEGIN°dONLNdéM®X¯+$
  3855. Print := cancel;°dONLNd£W®b‰*
  3856. Exit(Print);°dONLNd≥aÑlò(à¢END;°dONLNdΩa\lu)ÿ {If}°dONLNdΔuÑÄV(ú¢*IF PrError <> noErr THEN Print := PrError;°dONLNdÙâÑîÚ*{ that’s all for now } ¡4¡˘
  3857. (÷68) of 13(÷i"PR 9 - Print Dialogs: Adding Items+M.PR.PrintDialogsAddingItemsˇ
  3858. û◊#ˇ ˇˇˇˇ#◊ 
  3859. IR,Times
  3860. .+Z-Developer Support Center(-Ï
  3861. March 1988 /X/,
  3862. Courier
  3863.     °dONLNd'Ñ2ò(N¢END;°dONLNd 'Ä2≤)¸
  3864.  { Print }°dONLNd;`F“(b~J{------------------------------------------------------------------------}°dONLNdcO`Z~*BEGIN °dONLNdpO\Zé)¸
  3865.  {PROGRAM}°dONLNd}cÑnÚ(ä¢UnloadSeg(@_DataInit);°dONLNdîcn‹)ê( {remove data initialization code before°dONLNd√mxn*
  3866.   any allocations}°dONLNdÿwÑÇ„(û¢InitGraf(@thePort);°dONLNdÓÅÑå∂*
  3867.  
  3868. InitFonts;°dONLNd˚ãÑñ*
  3869. FlushEvents(everyEvent,0);°dONLNdïц¿*
  3870. InitWindows;°dONLNd'üÑ™∂*
  3871.  
  3872. InitMenus;°dONLNd4©Ñ¥ß*
  3873. TEInit;°dONLNd>≥ÑæŸ*
  3874. InitDialogs(NIL);°dONLNdRΩÑ»ª*
  3875. InitCursor;°dONLNd`—Ñ‹G*'{ call the routine that does printing }°dONLNdä€ÑÊ„*
  3876. FirstBoxValue := 0;°dONLNdü€Ê“)ê& { value of our first additional box }°dONLNd»ÂÑÌ( ¢SecondBoxValue := 0; °dONLNdfiÂ√)ê# { value of our second addtl. box }°dONLNdÔÑ˙=(¢%PrOpen;    { Open the Print Manager }°dONLNd,˘Ñ˜*
  3877. IF PrError = noErr THEN°dONLNdG®‘+$
  3878. <err := Print     { This actually brings up the modified Job °dONLNdà
  3879. 1+H
  3880.  
  3881.      dialog }°dONLNdòÑ"∂(>¢
  3882. ELSE BEGIN°dONLNd¶!®,R+$
  3883. "{tell the user that PrOpen failed}°dONLNdÀ+Ñ6ò(R¢END;°dONLNd“?ÑJy*1PrClose;    { Close the Print Manager and leave }°dONLNdI`Tt(p~END.
  3884. °dONLNd
  3885. k<z.(ñZ The Lightspeed C Example Program
  3886. °dONLNd+Ü<í†*J/* NOTE: Apple reserves the top half of the screen (where the current DITL°dONLNdví<ûT* <items are located). Applications may use the bottom half of °dONLNd≤íTû˛(∫r#the screen to add items, but should°dONLNd÷û<™Ê(ΔZ%not change any items in the top half °dONLNd¸û™9)¥of the screen. °dONLNd û9™˛)I&An application should expand the print°dONLNd2™<∂ (“Z0dialogs only as much as is absolutely necessary.
  3887.     °dONLNdc∂<¡F* */°dONLNdf <’ï*E/* Note: A global search and replace of 'Job' with 'Stl' will produce°dONLNdÆ‘`fl#+$
  3888. 'code that modifies the style dialogs */°dONLNd÷fi<È™(Z#include <DialogMgr.h>°dONLNdÌË<Û•*
  3889. #include <MacTypes.h>°dONLNdÚ<˝™*
  3890. #include <Quickdraw.h>°dONLNd¸<¥*
  3891. #include <ResourceMgr.h>°dONLNd3<™*
  3892. #include <WindowMgr.h>°dONLNdJ<õ*
  3893. #include <pascal.h>°dONLNd^<%•*
  3894. #include <printmgr.h>°dONLNdt$</Ç*
  3895. #define nil 0L°dONLNdÉB<M»*static TPPrDlg PrtJobDialog;°dONLNd°BMõ)ÿ/* pointer to job dialog */°dONLNdΩV<aF(}Z/*°dONLNd¿V`a#)$'This points to the following structure:°dONLNdÎj`uí*
  3896.   struct {°dONLNd˘tÑ +$
  3897.   DialogRecord°dONLNdt)lDlg;°dONLNd
  3898. t)$  °dONLNdt8ó)$(The Dialog window)°dONLNd&~Ñâ±(•¢      ProcPtr°dONLNd1~â")l
  3899. pFltrProc;°dONLNd<~8âí)H(The Filter Proc.) ¡X¡
  3900. (÷Z"PR 9 - Print Dialogs: Adding Items(÷ˇ9) of 13(ÏZM.PR.PrintDialogsAdding Itemsˇä◊#ˇ ˇˇˇˇ#◊ 
  3901. IR,Times
  3902. .+6-Macintosh Technical Notes /4/˘,
  3903. Courier
  3904.     °dONLNd`(ç+H      ProcPtr°dONLNd Ã(˛)l
  3905. pItemProc;°dONLNd(™)H(The Item evaluating proc. -- °dONLNd;'2J(Nwe'll change this)°dONLNdP1`<ç(X~      THPrint°dONLNd[1Ã<˛)l
  3906. hPrintUsr;°dONLNdf1<ñ)H(The user's print record.)°dONLNdÉ;`Fç(b~      Boolean°dONLNdé;ÃFÍ)lfDoIt;°dONLNdòE`Pç(l~      Boolean°dONLNd£EÃPÍ)lfDone;°dONLNd≠O`Zj(v~  °dONLNd∞OÑZV)$*(Four longs -- reserved by Apple Computer)°dONLNd›Y`d~(Ä~  long°dONLNdÊYÃdÔ)llUser1;°dONLNdÛc`n~(ä~  long°dONLNd¸cÃnÔ)llUser2;°dONLNdm`x~(î~  long°dONLNdmÃxÔ)llUser3;°dONLNdw`Ç~(û~  long°dONLNd%wÃÇÔ)llUser4;°dONLNd/Ååê(®6   } TPrDlg; *TPPrDlg;  °dONLNdJãñ"*
  3907. */°dONLNdMü™"*/*°dONLNdPü<™)$,Declare ‘pascal’ functions and procedures */°dONLNd}©¥ü(–6pascal Boolean PrDlgMain();°dONLNdö©Ã¥Ä)¥$/* Print manager’s dialog handler */°dONLNdø≥æü(⁄6pascal TPPrDlg PrJobInit();°dONLNd‹≥ÃæÖ)¥%/* Gets standard print job dialog. */°dONLNdΩ»Æ(‰6pascal TPPrDlg MyJobDlgInit();°dONLNd!Ωûl)¥ /* Our extention to PrJobInit */°dONLNdB«“ï(Ó6pascal void MyJobItems();°dONLNd]«Ã“X)¥/* Our modal item handler */°dONLNdz€Êr(6#define MyDITL 256°dONLNdè€ÃÊè)¥'/* resource ID of my DITL to be spliced°dONLNdæÂs+H
  3908. on to job dialog */°dONLNd“r(*6THPrint hPrintRec;°dONLNdÁÃX)¥/* handle to print record */°dONLNd
  3909. ê(46short FirstBoxValue = 0;°dONLNd
  3910. Ãè)¥'/* value of our first additional box */°dONLNdF"ï(>6short SecondBoxValue = 0;°dONLNdaÃ"Ä)¥$/* value of our second addtl. box */°dONLNdÜ!,m(H6long prFirstItem;°dONLNdõ!,Ü)ÿ/* save our first item here */°dONLNd∫+6m(R6long prPItemProc;°dONLNdŒ+Ã6®)¥,/* we need to store the old itemProc here */°dONLNd˚?Jè(f6K/*-----------------------------------------------------------------------*/°dONLNdHI<Tn+$
  3911.  
  3912. WindowPtr °dONLNdSIÑT±)H    MyWindow;°dONLNd^S<^Z(zZOSErr °dONLNdeS`^t)$err;°dONLNdk]<h_(ÑZStr255 °dONLNds]Ñh¢)HmyStr;°dONLNdzgr6(é6main()°dONLNdÅq|*
  3913. {°dONLNdÖ{<ÜU+$
  3914. Rect °dONLNdå{Ñܨ)HmyWRect;°dONLNdòè<öõ(∂ZInitGraf(&thePort);°dONLNd≠ô<§x*
  3915. InitFonts();°dONLNdª£<ÆÇ*
  3916. InitWindows();°dONLNdÀ≠<∏x*
  3917. InitMenus();°dONLNdŸ∑<¬ë*
  3918. InitDialogs(nil);°dONLNdÏ¡<Ã}*
  3919.  
  3920. InitCursor();°dONLNd˙À÷'(Ú6   °dONLNd˛À<÷·)$!SetRect(&myWRect,50,260,350,340);°dONLNd#fl<Í    *)/* call the routine that does printing */°dONLNdNÈ<Ùi*
  3921.     PrOpen();°dONLNdYÛ<˛Ç*
  3922. err = Print();°dONLNdk<n*
  3923. PrClose();°dONLNdvT(86 } /* main */°dONLNdÉ%0î*L/*------------------------------------------------------------------------*/°dONLNd–9DY*
  3924. OSErr Print()°dONLNdfiMX*{°dONLNd·W<bw+$
  3925. ?/* call PrJobInit to get pointer to the invisible job dialog */°dONLNd"a<l1*
  3926. 1hPrintRec = (THPrint)(NewHandle(sizeof(TPrint)));°dONLNdUk<v¥*
  3927. PrintDefault(hPrintRec);°dONLNdou<Ä™*
  3928. PrValidate(hPrintRec);°dONLNdá<äØ*
  3929. if (PrError() != noErr)°dONLNd°â`îµ+$
  3930. return PrError(); ¡4¡˘
  3931. (÷610)
  3932.  of 13(÷i"PR 9 - Print Dialogs: Adding Items+M.PR.PrintDialogsAddingItemsˇ
  3933. ◊#ˇ ˇˇˇˇ#◊ 
  3934. IR,Times
  3935. .+Z-Developer Support Center(-Ï
  3936. March 1988 /X/,
  3937. Courier
  3938.     °dONLNd'`2(N~$PrtJobDialog = PrJobInit(hPrintRec);°dONLNd&1`<”*
  3939. if (PrError() != noErr)°dONLNd@;ÑFŸ+$
  3940. return PrError();°dONLNdWY`d-(Ä~)if (!PrDlgMain(hPrintRec, &MyJobDlgInit))°dONLNdÅY8d‚)ÿ"/* this line does all the stuff */°dONLNd¶cÑn (ä¢return Cancel;°dONLNd∂w`Ç”(û~if (PrError() != noErr)°dONLNd–ÅÑåŸ+$
  3941. return PrError();°dONLNdÊï<†¥(ºZ/* that's all for now */°dONLNd©<¥}*
  3942. } /* Print */°dONLNdΩ<»∏*L/*------------------------------------------------------------------------*/°dONLNd]—<‹*$pascal TPPrDlg MyJobDlgInit (hPrint)°dONLNdÇ€<Êá*
  3943. THPrint hPrint;°dONLNdíÂ<§*
  3944. H/* this routine appends items to the standard job dialog and sets up the°dONLNd‹Ô`˙P+$
  3945. 0user fields of the printing dialog record TPRDlg°dONLNd˘`7*
  3946. +This routine will be called by PrDlgMain */°dONLNd;<A(*Z{°dONLNd>
  3947. `y+$
  3948. short°dONLNdE
  3949. ®⁄)H
  3950. firstItem;°dONLNdQ
  3951. õ)l/* first new item number */°dONLNdp!`,y(H~short°dONLNdw!®,’)H    itemType;°dONLNdÇ!,◊)l'/* needed for GetDItem/SetDItem call */°dONLNd´+`6~(R~Handle°dONLNd≤+Ñ6¢)$itemH;°dONLNd∫5`@t(\~Rect°dONLNd¿5®@–)HitemBox;°dONLNdÃI`T¥(p~DfirstItem = AppendDITL (PrtJobDialog, MyDITL); /*call routine to do °dONLNdS8^[+ÿ
  3952. this */°dONLNd$g`r™(é~BprFirstItem = firstItem; /* save this so MyJobItems can find it */°dONLNdi{<ÜT(¢Z8/* now we'll set up our DITL items -- The "First Box" */°dONLNd£Ö`êá+$
  3953. ;GetDItem(PrtJobDialog,firstItem,&itemType,&itemH,&itemBox);°dONLNd‡è`ö*
  3954. !SetCtlValue(itemH,FirstBoxValue);°dONLNd£<Ƨ( ZH/* now we'll set up the second of our DITL items  -- The "Second Box" */°dONLNdN≠`∏ë+$
  3955. =GetDItem(PrtJobDialog,firstItem+1,&itemType,&itemH,&itemBox);°dONLNdç∑`¬
  3956. *
  3957. "SetCtlValue(itemH,SecondBoxValue);°dONLNd≤À<÷Æ(ÚZJ/* Now comes the part where we patch in our item handler.  We have to save°dONLNd˛’`‡+$
  3958. Pthe old item handler address, so we can call it if one of the standard items is °dONLNdOfl`ÍÎ*
  3959. Ohit, and put our item handler's address in pItemProc field of the TPrDlg struct°dONLNdüÈ<ÙF(Z*/°dONLNd£˝`<+$,prPItemProc = (long)PrtJobDialog->pItemProc;°dONLNd“<|(8Z@/* Now we'll tell the modal item handler where our routine is */°dONLNd`&K+$
  3960. /PrtJobDialog->pItemProc = (ProcPtr)&MyJobItems;°dONLNdF/<:≥(VZK/* PrDlgMain expects a pointer to the modified dialog to be returned.... */°dONLNdì9`Dƒ+$
  3961. return PrtJobDialog;°dONLNd™M<Xñ(tZ} /*myJobDlgInit*/°dONLNdΩk<v≥*K/*-----------------------------------------------------------------------*/°dONLNd    <ä'*//* here's the analogue to the SF dialog hook */ ¡X¡
  3962. *0"PR 9 - Print Dialogs: Adding Items(÷˙11)
  3963.  of 13(ÏZM.PR.PrintDialogsAdding Itemsˇ î◊#ˇ ˇˇˇˇ#◊ 
  3964. IR,Times
  3965. .+6-Macintosh Technical Notes /4/˘,
  3966. Courier
  3967.     °dONLNd(‡*(pascal void MyJobItems(theDialog,itemNo)°dONLNd)'2;*
  3968. TPPrDlg°dONLNd1'`2í)H
  3969. theDialog;°dONLNd<1<6(X6short °dONLNdC1<<_)$itemNo;°dONLNdKEPr(l6{ /* MyJobItems */°dONLNd_O<ZZ+$
  3970. short °dONLNdfO`ZÉ)$myItem;°dONLNdoY<dZ(ÄZshort °dONLNdvY`dí)$
  3971. firstItem;°dONLNdÑm<xU(îZshort°dONLNdãmÑx±)H    itemType;°dONLNdñmx≥)l'/* needed for GetDItem/SetDItem call */°dONLNdøw<ÇZ(ûZHandle°dONLNdΔw`Ç~)$itemH;°dONLNdŒÅ<åP(®ZRect°dONLNd‘ÅÑå¨)HitemBox;°dONLNd‡ï<†ö(ºZFfirstItem = prFirstItem; /* remember, we saved this in myJobDlgInit */°dONLNd(ü<™»*
  3972. myItem = itemNo-firstItem+1;°dONLNdEü™ê)¥ /* "localize" current item No */°dONLNdg©<¥å(–Zif (myItem > 0) °dONLNdx©®¥â)l-/* if localized item > 0, it's one of ours */°dONLNdß≥<æA(⁄Z{°dONLNd´Ω`»-+$
  3973. )/* find out which of our items was hit */°dONLNd◊«`“i*
  3974. 5GetDItem(theDialog,itemNo,&itemType,&itemH,&itemBox);°dONLNd—`‹´*
  3975. switch (myItem)°dONLNd!€`Êe*
  3976. {°dONLNd&ÂÑß+$
  3977. case 1:°dONLNd2Ô®˙ù+$
  3978. 1/* invert value of FirstBoxValue and redraw it */°dONLNdh˘®*
  3979. FirstBoxValue ^= 1;°dONLNdÄ®M*
  3980. !SetCtlValue(itemH,FirstBoxValue);°dONLNd¶
  3981. ®Δ*
  3982. break;°dONLNd∞!Ñ,ß(H¢case 2:°dONLNdº+®6¢+$
  3983. 2/* invert value of SecondBoxValue and redraw it */°dONLNdÛ5®@ *
  3984. SecondBoxValue ^= 1;°dONLNd ?®JR*
  3985. "SetCtlValue(itemH,SecondBoxValue);°dONLNd3I®TΔ*
  3986. break;°dONLNd=SÑ^$(z¢ default: Debugger(); /* OH OH */°dONLNda]`h¶(Ñ~} /* switch */°dONLNdqg<rØ(éZ} /* if (myItem > 0) */°dONLNdäq<|Å*
  3987. Aelse /* chain to standard item handler, whose address is saved in°dONLNdœ{ÑÜ +H
  3988. prPItemProc */°dONLNdflÖ<êA(¨Z{°dONLNd„è`ö-+$
  3989. )CallPascal(theDialog,itemNo,prPItemProc);°dONLNdô<§A(¿Z}°dONLNd£Ær( 6} /* MyJobItems */
  3990. °dONLNd#≈‘Ä*&The Rez Source
  3991.     °dONLNd2‡Îr*#include "types.r"°dONLNdEÙˇã*resource 'DITL' (256) {°dONLNd^˛<    A+$
  3992. {°dONLNd`˛`    )$!/* array DITLarray: 2 elements */°dONLNdÑ`ç*
  3993.     /* [1] */°dONLNdê`∞*
  3994. {8, 0, 24, 112},°dONLNd£`'í*
  3995.  
  3996. CheckBox {°dONLNd±&Ñ1¨+$
  3997. enabled,°dONLNdΩ0Ñ;ª*
  3998. "First Box"°dONLNdÀ:`Ej(a~};°dONLNd–D`Oç*
  3999.     /* [2] */°dONLNd‹N`Y∫*
  4000. {8, 175, 24, 287},°dONLNdÒX`cí*
  4001.  
  4002. CheckBox {°dONLNdˇbÑm¨+$
  4003. enabled,°dONLNd lÑw¿*
  4004. "Second Box"°dONLNdv`Åe(ù~}°dONLNdÄ<ãA(ßZ}°dONLNdäï"(±6}; ¡4¡˘
  4005. *%12)
  4006.  of 13(÷i"PR 9 - Print Dialogs: Adding Items+M.PR.PrintDialogsAddingItemsˇ‹◊#ˇ ˇˇˇˇ#◊ 
  4007. IR,Times
  4008. .+Z-Developer Support Center(-Ï
  4009. March 1988 /X/
  4010. °dONLNdA<M¶(iZFurther Reference: lXl°dONLNdNNZR+
  4011. •°dONLNdN`Z«)The Printing Manager°dONLNd*ZNfR(Çl•°dONLNd,Z`f¿)The Dialog Manager ¡X¡
  4012. (÷Z"PR 9 - Print Dialogs: Adding Items(÷˙13)
  4013.  of 13(ÏZM.PR.PrintDialogsAdding Itemsˇû◊#ˇ ˇˇˇˇ#◊†Ç 
  4014. /ZÅ#
  4015.     0Ià:µú9"{    ˇˇˇˇˇˇˇˇ#†ƒ°d
  4016. ONLNf˛†å°d1drw2…-·_ġˇˇˇˇˇè°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˙ó@†ò,Times
  4017. .R…R…+]BNew Technical Notes†ô°ddrw2:°„†ó°d1drw2eÙġˇˇˇˇˇP°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚ÄE¿†ò
  4018. ({ïDeveloper Support†ô°ddrw2:°„†ó°d`drw2-ÔˇˇˇˇˇˇKÔ- Z  ffZ°d1drw2 ¿˙ÈˇˇˇˇˇˇK°ñ x°ddrw2:°ddrw2:$°d4drw2:0°öˇÙĆò
  4019. 0(UÔ†ô°ddrw2:°„†ó°d1drw2ÔÊ˙ˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:    °öˇ˝Ä†ò
  4020.     +&    ®†ô°ddrw2:°„†ó°d1drw2Â-¯yˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚Ä%†ò
  4021. (Z\    Macintosh†ô°ddrw2:°„†ó†ç°ddrw2D†É
  4022. IR.°dONLNdn<Åy(õZ#PR 10 - A Printing Loop That Cares…
  4023. °dONLNd$Ä<ès*Printing
  4024. °dONLNd.õ<ßt* Revised by:°dONLNd:õÑß)HPete “Luke” Alexander°dONLNdPõæß˛(√‹ October 1990°dONLNd]ß<≥q(œZ Written by:°dONLNdißÑ≥–)HGinger Jernigan°dONLNdyß±≥˛(œœSeptember 1987°dONLNdàø<ÀW(ÁZThis °dONLNdçøWÀ˛)OTechnical Note discusses opening and closing the Printing Manager with calls to,
  4025. Courier°dONLNd›À<◊m(ÙZ_PrOpen°dONLNd‰ÃmÿÑ)1 and °dONLNdÈÀÑ◊º)_PrClose°dONLNdÒúÿë)8/ as well as how to handle errors at print time.°dONLNd!ÿ<‰ì(ZChanges since °dONLNd/ÿì‰Â)W
  4026. October 1989:°dONLNd<ÿ‰˛)R8  Added the section on error checking, incorporating the°dONLNdu‰< ( Z*error code descriptions formerly found in °dONLNdü‰ ˛)‰&Technical Note #72, Optimizing For The°dONLNdΔ<¸—(ZJLaserWriter—Techniques and an updated version of the information formerly °dONLNd—¸˛(Ôfound in°dONLNd¸<u($Z=Technical Note #118, How To Check and Handle Printing Errors. 3X3
  4027. °dONLNdW!<0è*( Introduction
  4028. °dONLNdd=<I5*/At one time, Apple recommended that developers °dONLNdì=5IK)˘call °dONLNdò<KH|)_PrOpen°dONLNdü=|I˛)1 at the beginning of their°dONLNd∫J<Và(rZapplication and °dONLNd IàU¿)L_PrClose°dONLNd“J¿Vñ)8. at the end, before returning to the Finder.  °dONLNdJñV˛)÷This recommendation°dONLNdV<bŸ(~ZZwas in the ancient past when an application only had to deal with a single printer driver.°dONLNdon<z∑*QAs more printer drivers became available, it became important for an application °dONLNd¿n∑z˛(ñ’to consider the°dONLNd–z<Üt(¢Z?presence of other applications and how opening and closing the °dONLNdztܲ(¢íprinter driver affected them.°dONLNd.Ü<í€(ÆZ The user could open the Chooser °dONLNdNÜ€í˛)ü=at any time and change the current printer driver without the°dONLNdåí<ûÍ(∫ZVcurrent application’s knowledge.  If an application followed the old philosophy and a °dONLNd‚íÍû˛(∫user°dONLNdÁû<™ (ΔZ)changed the current printer driver while °dONLNdû ™˛)œ/running the application, the next time the user°dONLNd@™<∂ö(“ZIattempted to print, the wrong driver would be open, the Printing Manager °dONLNdâ™ö∂˛(“∏would not be able to°dONLNdû∂<¬_(fiZ>find the necessary resources, and the user would get an error.
  4029. °dONLNd›⁄<È*'The Current Recommendation
  4030. °dONLNd¯ı<a*:DTS currently recommends that applications open and close °dONLNd2ıaπ(the printer driver °dONLNdEıπ“)Xeach°dONLNdIı“˛)     time the°dONLNdS<
  4031. Ò()Z&application uses the Printing Manager.°dONLNdz<%É*
  4032. MPW Pascal
  4033.     °dONLNdÖ1<<÷*R*------ PrintStuff ---------------------------------------------------------------°dONLNd◊1÷<€(XÙ-°dONLNdÿ;<FF(bZ*}°dONLNd€E<PK*
  4034. {**°dONLNdflO<ZK*
  4035.  **°dONLNd„O`Zæ)$FPrintStuff will call all of the necessary Print Manager calls to print°dONLNd*Y<dK(ÄZ **°dONLNd.Y`dæ)$Fa document.  It checks PrError() after each Print Manager call.  If an°dONLNduc<nK(äZ **°dONLNdyc`n™)$Berror is found, all of the Print Manager open calls (i.e., PrOpen,°dONLNdºm<xK(îZ **°dONLNd¿m`xØ)$CPrOpenDoc...) will have a corresponding close call before the error°dONLNdw<ÇK(ûZ **°dONLNdw`Çæ)$Fis posted to the user.  You want to use this approach to make sure the°dONLNdOÅ<åK(®Z **°dONLNdSÅ`åØ)$CPrint Manager closes properly and all temporary memory is released.°dONLNdóã<ñP(≤Z **} ¡X¡
  4036. *$#PR 10 - A Printing Loop That Cares…(÷ˇ1) of 11(ÏZM.PR.PrintLoopˇ°¿Ù%%DSIDICT:_cv
  4037. currentdict /bu known {bu}if
  4038. userdict /_cv known not{userdict /_cv 30 dict put}if
  4039. _cv begin
  4040. /bdf{bind def}bind def
  4041. currentscreen/cs exch def/ca exch def/cf exch def
  4042. /setcmykcolor where{/setcmykcolor get /cvcmyk exch def}{/cvcmyk{1 sub 4 1 roll 3{3 index add neg dup 0 lt{pop 0}if 3 1 roll}repeat setrgbcolor pop}bdf }ifelse
  4043. /ss{//cf //ca //cs setscreen}bdf
  4044. /stg{ss setgray}bdf
  4045. /strgb{ss setrgbcolor}bdf
  4046. /stcmyk{ss cvcmyk}bdf
  4047. /min1{dup 0 eq{pop 1}if}bdf
  4048. end
  4049. currentdict /bn known {bn}if
  4050. †ø Œ◊#ˇ ˇˇˇˇ#◊ 
  4051. IR,Times
  4052. .+6-Macintosh Technical Notes /4/˘,
  4053. Courier
  4054.     °dONLNd'2Å*!PROCEDURE PrintStuff;°dONLNd;F'*VAR°dONLNdEPE*
  4055.       copies,°dONLNd$OZT*
  4056.   firstPage,°dONLNd1YdO*
  4057.   lastPage,°dONLNd=cn;*
  4058.   loop,°dONLNdEmxm*
  4059.   numberOfCopies,°dONLNdWwÇY*
  4060.  
  4061.   pageNumber,°dONLNdeÅåw*
  4062.   printmgrsResFile,°dONLNdyãñÃ*
  4063. $  realNumberOfPagesInDoc  : Integer;°dONLNdûï†Ã*
  4064. $  PrintError              : LongInt;°dONLNd√ü™Ã*
  4065. $  oldPort                 : GrafPtr;°dONLNdË©¥Ã*
  4066. $  thePrRecHdl             : THPrint;°dONLNd
  4067. ≥æ—*
  4068. %  thePrPort               : TPPrPort;°dONLNd3Ω»÷*
  4069. &  theStatus               : TPrStatus;°dONLNdZ—‹1*BEGIN°dONLNd`€Êw*
  4070.   GetPort(oldPort);°dONLNdtÔ˙1*  {**°dONLNdz˘∑*
  4071. S      UnLoadTheWorld will swap out ALL unneeded code segments and data that are NOT°dONLNdŒ^*
  4072.       required°dONLNd›
  4073. Ö*
  4074. I      during print time. Your print code must be a separate code segment.°dONLNd'"1*
  4075.   **}°dONLNd-!,m*
  4076.   UnLoadTheWorld;°dONLNd?5@*4  thePrRecHdl := THPrint(NewHandle(SIZEOF(TPrint)));°dONLNdtIT!*5  IF (MemError = noErr) AND (thePrRecHdl <> NIL) THEN°dONLNd™S^E*
  4077.         BEGIN°dONLNd¥]hY*
  4078.  
  4079.       PrOpen;°dONLNd¬grΩ*
  4080. !        IF (PrError = noErr) THEN°dONLNd‰q|c*
  4081.           BEGIN°dONLNdÙ{Üc*
  4082.             {**°dONLNdÖêä*
  4083. J                Save the current resource file (i.e. the printer driver's)°dONLNdOèöä*
  4084. J                so the driver will not lose its resources upon return from°dONLNdöô§Æ*
  4085.                 the pIdleProc.°dONLNdπ£Æh*
  4086.              **}°dONLNd ≠∏Ô*
  4087. +            printmgrsResFile := CurResFile;°dONLNdˆ∑¬÷*
  4088. &            PrintDefault(thePrRecHdl);°dONLNdÀ÷—*%            IF (PrError = noErr) THEN°dONLNdC’‡w*
  4089.               BEGIN°dONLNdWflÍ*
  4090. 2                IF (PrStlDialog(thePrRecHdl)) THEN°dONLNdäÈÙã*
  4091.                   BEGIN°dONLNd¢Û˛ã*
  4092.                     {**°dONLNd∫˝î*
  4093. L                        DetermineNumberOfPagesinDoc determines the number of°dONLNd®*
  4094. P                        pages contained in the document by comparing the size of°dONLNdXº*
  4095. T                        the document with rPage from the TPrInfo record (IM II-150).°dONLNd≠&î*
  4096. L                        It returns the number of pages required to print the°dONLNd˙%0l*
  4097. D                        document for the currently selected printer.°dONLNd?/:ê*
  4098.                      **}°dONLNdXCNÖ*I                    realNumberOfPagesinDoc := DetermineNumberOfPagesinDoc°dONLNd¢MX£*
  4099. O                                                  (thePrRecHdl^^.prInfo.rPage); ¡4¡˘
  4100. *b2) of 11(÷Z#PR 10 - A Printing Loop That Cares…+YM.PR.PrintLoopˇé◊#ˇ ˇˇˇˇ#◊ 
  4101. IR,Times
  4102. .+Z-Developer Support Center(-Ê October 1990 /X/,
  4103. Courier
  4104.     °dONLNd'<2J(NZ6                    IF (PrJobDialog(thePrRecHdl)) THEN°dONLNd81<<√*
  4105.                       BEGIN°dONLNdT;<F√*
  4106.                         {**°dONLNdpE<PΩ*
  4107. M                            Get the number of copies of the document that the°dONLNdæO<ZÃ*
  4108. P                            user wants printed from iCopies of the TPrJob record°dONLNdY<d*
  4109. (                            (IM II-151).°dONLNd8c<n»*
  4110.                          **}°dONLNdUw<Çö*F                        numberOfCopies := thePrRecHdl^^.prJob.iCopies;°dONLNdúã<ñ√*                        {**°dONLNd∏ï<†Ω*
  4111. M                            Get the first and last pages of the document that°dONLNdü<™÷*
  4112. R                            were requested to be printed by the user from iFstPage°dONLNdY©<¥Ω*
  4113. M                            and iLastPage from the TPrJob record (IM II-151).°dONLNdß≥<æ»*
  4114.                          **}°dONLNdƒ«<“Ü*B                        firstPage := thePrRecHdl^^.prJob.iFstPage;°dONLNd—<‹Å*
  4115. A                        lastPage := thePrRecHdl^^.prJob.iLstPage;°dONLNdIÂ<√*                        {**°dONLNdeÔ<˙w*
  4116. ?                            Print "all" pages in the print loop°dONLNd•˘<»*
  4117.                          **}°dONLNd¬
  4118. <^*:                        thePrRecHdl^^.prJob.iFstPage := 1;°dONLNd˝<"m*
  4119. =                        thePrRecHdl^^.prJob.iLstPage := 9999;°dONLNd;+<6√*                        {**°dONLNdW5<@Ω*
  4120. M                            Determine the "real" number of pages contained in°dONLNd•?<JΩ*
  4121. M                            the document.  Without this test, you would print°dONLNdÛI<Tˇ*
  4122. '                            9999 pages.°dONLNdS<^»*
  4123.                          **}°dONLNd8g<rã*C                        IF (realNumberOfPagesinDoc < lastPage) THEN°dONLNd|q<|m*
  4124. =                          lastPage := realNumberOfPagesinDoc;°dONLNd∫Ö<ê‡*T                        PrintingStatusDialog := GetNewDialog(257, NIL, POINTER(-1));°dONLNd(ô<§√*                        {**°dONLNdD£<Æ€*
  4125. S                            Print the number of copies of document requested by the°dONLNdõ≠®∏⁄+l
  4126.  
  4127.       user°dONLNd¶∑<¬J(fiZ6                            from the Print Job Dialog.°dONLNd›¡<û*
  4128.                          **}°dONLNd˙’<‡h*<                        For copies := 1 To numberOfCopies Do°dONLNd7fl<Í◊*
  4129.                           BEGIN°dONLNdWÛ<˛◊*                            {**°dONLNdw˝<—*
  4130. Q                                Install a pointer to your pIdle proc in my print °dONLNdÃÃ+ê
  4131.     record.°dONLNdÿ<‹(8Z                              **}°dONLNd˘<&r*
  4132. >                             thePrRecHdl^^.prJob.pIdleProc := °dONLNd>%Ã0N+ê
  4133. @checkMyPrintDialogButton;°dONLNdY9<D◊(`Z                            {**°dONLNdyC<N÷*
  4134. R                                Restore the resource file to the printer driver's.°dONLNdÃM<X‹*
  4135.                               **}°dONLNdÌW<bY*
  4136. 9                            UseResFile(printmgrsResFile);°dONLNd    'k<vÆ*J                            thePrPort := PrOpenDoc(thePrRecHdl, NIL, NIL);°dONLNd    r<äE*5                            IF (PrError = noErr) THEN°dONLNd    ®â<îÎ*
  4137. #                              BEGIN ¡X¡
  4138. *&#PR 10 - A Printing Loop That Cares…(÷ˇ3) of 11(ÏZM.PR.PrintLoopˇ~◊#ˇ ˇˇˇˇ#◊ 
  4139. IR,Times
  4140. .+6-Macintosh Technical Notes /4/˘,
  4141. Courier
  4142.     °dONLNd(«*#                                {**°dONLNd$'2ô*
  4143. M                                    Print the range of pages of the document °dONLNdw1Ã<˘+¥
  4144.     requested°dONLNdÅ;Fä(b6J                                    by the user from the Print Job Dialog.°dONLNdÃEPÃ*
  4145. $                                 **}°dONLNdÒOZ0*
  4146. 8                                pageNumber := firstPage;°dONLNd*Yd£*
  4147. O                                WHILE ((pageNumber <= lastPage) AND (PrError = °dONLNd}c®nÈ+ê
  4148.  
  4149.    noErr)) DO°dONLNdãmx€(î6'                                  BEGIN°dONLNd≥ÅåS*?                                    PrOpenPage(thePrPort, NIL);°dONLNdÛï†S*?                                      IF (PrError = noErr) THEN°dONLNd3ü™˘*
  4150. -                                        BEGIN°dONLNda©¥˘*
  4151. -                                          {**°dONLNdè≥æ®*
  4152. P                                              rPage (IM II-150) is the printable°dONLNd‡Ω»û*
  4153. N                                              area for the currently selected °dONLNd5«“'+ÿ
  4154.    printer.°dONLNdA—‹≤(¯6R                                              By passing the current enables your °dONLNdô€ÊΩ+ÿ
  4155. )   app to use the same routine to draw to°dONLNd»ÂÃº( Í0          the screen and the printer's GrafPort.°dONLNd˘Ô˙˛(6.                                           **}°dONLNd(®*P                                          DrawStuff (thePrRecHdl^^.prInfo.rPage,°dONLNdz
  4156. Ö*
  4157. I                                                     GrafPtr (thePrPort),°dONLNd≈"]*
  4158. A                                                     pageNumber);°dONLNd!,Ù*
  4159. ,                                        END;°dONLNd4+6I*
  4160. =                                      PrClosePage(thePrPort);°dONLNdr5@g*
  4161. C                                      pageNumber := pageNumber + 1;°dONLNd∂?Jq*
  4162. E                                  END;  {**  End pagenumber loop  **}°dONLNd¸IT¬*
  4163. "                              END;°dONLNdS^*
  4164. 2                            PrCloseDoc(thePrPort);°dONLNdR]h5*
  4165. 9                          END;  {**  End copies loop  **}°dONLNdåq|©*                          {**°dONLNd™{Ü≤*
  4166. R                              The printing job is being canceled by the request of°dONLNd˝Öê∑*
  4167. S                              the user from the Print Style Dialog or the Print Job°dONLNdQèö≤*
  4168. R                              Dialog.  PrError will be set to iPrAbort to tell the°dONLNd§ô§û*
  4169. N                              Print Manager to abort the current printing job.°dONLNd󣮮*
  4170.                            **}°dONLNd≠∏ï*
  4171.                       END°dONLNd,∑¬§*
  4172.                         ELSE°dONLNdI¡Ã≤*
  4173. R                      PrSetError(iPrAbort);   {**  Cancel from the job dialog  **}°dONLNdúÀ÷Å*
  4174.                   END°dONLNd≤’‡ê*
  4175.                     ELSE°dONLNdÀflÍ®*
  4176. P                  PrSetError(iPrAbort);   {**  Cancel from the style dialog  **}°dONLNd    ÈÙr*
  4177.               END;°dONLNd    /Û˛^*
  4178.           END;°dONLNd    >˝û*
  4179. N    IF (thePrRecHdl^^.prJob.bJDocLoop = bSpoolLoop) and (PrError = noErr) THEN°dONLNd    ç+*
  4180. 7      PrPicFile(thePrRecHdl, NIL, NIL, NIL, theStatus);°dONLNd    ≈&;*    {**°dONLNd    Õ%0®*
  4181. P        Grab the printing error before you close the Print Manager and the error°dONLNd
  4182. /:w*
  4183.         disappears.°dONLNd
  4184. 39D@*
  4185.      **}°dONLNd
  4186. <MXö*    PrintError := PrError;°dONLNd
  4187. WalT*     PrClose; ¡4¡˘
  4188. *N4) of 11(÷Z#PR 10 - A Printing Loop That Cares…+YM.PR.PrintLoopˇ
  4189. T◊#ˇ ˇˇˇˇ#◊ 
  4190. IR,Times
  4191. .+Z-Developer Support Center(-Ê October 1990 /X/,
  4192. Courier
  4193.     °dONLNd'<2_(NZ    {**°dONLNd1<<≥*
  4194. K        You do not want to report any printing errors until you have fallen°dONLNdT;<F∏*
  4195. L        through the printing loop. This will make sure that ALL of the Print°dONLNd°E<PÆ*
  4196. J        Manager's open calls have their corresponding close calls, thereby°dONLNdÏO<Z≥*
  4197. K        enabling the Print Manager to close properly and that all temporary°dONLNd8Y<d*
  4198. (        memory allocations are released.°dONLNdac<nd*
  4199.      **}°dONLNdjw<Ç·*!    IF (PrintError <> noErr) THEN°dONLNdåÅ<å˙*
  4200. &      PostPrintingErrors (PrintError);°dONLNd≥ï<†d*    END;°dONLNdº©<¥“*  IF (thePrRecHdl <> NIL) THEN°dONLNd‹≥<æˇ*
  4201. '    DisposHandle(Handle (thePrRecHdl));°dONLNd«<“ˇ*'  IF (PrintingStatusDialog <> NIL) THEN°dONLNd-—<‹ˇ*
  4202. '    DisposDialog(PrintingStatusDialog);°dONLNdUÂ<õ*  SetPort(oldPort);°dONLNdiÔ<˙æ*
  4203. END;  {**  PrintStuff  **}
  4204. °dONLNdÑ<h*MPW C
  4205.     °dONLNdä<(€*S/*------ PrintStuff ---------------------------------------------------------------°dONLNd›€(‡(D˘-°dONLNdfi'<2F(NZ*/°dONLNd·1<<K*
  4206.  **°dONLNdÂ;<FΩ*
  4207. M **    PrintStuff will call all of the necessary Print Manager calls to print°dONLNd3E<P—*
  4208. Q **    a document. It checks PrError() after each Print Manager call. If an error°dONLNdÖO<Z—*
  4209. Q **    is found, all of the Print Manager open calls (i.e., PrOpen, PrOpenDoc...)°dONLNd◊Y<d€*
  4210. S **    will have a corresponding close call before the error is posted to the user.°dONLNd+c<n€*
  4211. S **    You want to use this approach to make sure the Print Manager closes properly°dONLNdm<x*
  4212. , **    and all temporary memory is released.°dONLNd¨w<ÇP*
  4213.  **/°dONLNd±ã<ññ*void PrintStuff ()°dONLNdƒï<†A*
  4214. {°dONLNdΔü<™Ø*
  4215.   GrafPtr      oldPort;°dONLNdfi©<¥™*
  4216.   short        copies,°dONLNdı≥<æπ*
  4217.                firstPage,°dONLNdΩ<»¥*
  4218.                lastPage,°dONLNd(«<““*
  4219.                numberOfCopies,°dONLNdG—<‹‹*
  4220.                 printmgrsResFile,°dONLNdh€<Ê˙*
  4221. &               realNumberOfPagesinDoc,°dONLNdèÂ<æ*
  4222.                pageNumber,°dONLNd™Ô<˙æ*
  4223.                PrintError;°dONLNd≈˘<√*
  4224.   THPrint      thePrRecHdl;°dONLNd·<π*
  4225.   TPPrPort     thePrPort;°dONLNd˚
  4226. <π*
  4227.   TPrStatus    theStatus;°dONLNd!<,†*  GetPort(&oldPort);°dONLNd*5<@P* /**°dONLNd/?<JÆ*
  4228. J     UnLoadTheWorld will swap out ALL unneeded code segments and data that°dONLNdzI<T≥*
  4229. K     are NOT required during print time. Your print code must be a separate°dONLNdΔS<^ñ*
  4230.      code segment.°dONLNdŸ]<hU*
  4231.   **/°dONLNdflq<|†*  UnLoadTheWorld ();°dONLNdÙ{<ÜO*
  4232. 7  thePrRecHdl = (THPrint)  NewHandle (sizeof (TPrint)); ¡X¡
  4233. *4#PR 10 - A Printing Loop That Cares…(÷ˇ5) of 11(ÏZM.PR.PrintLoopˇ¨◊#ˇ ˇˇˇˇ#◊ 
  4234. IR,Times
  4235. .+6-Macintosh Technical Notes /4/˘,
  4236. Courier
  4237.     °dONLNd(,* /**°dONLNd'2Ä*
  4238. H     Check to make sure that the memory manager did not produce an error°dONLNdN1<î*
  4239. L     when it allocated the print record handle and make sure it did not pass°dONLNdõ;Fã*
  4240.      back a nil handle.°dONLNd≥EP1*
  4241.   **/°dONLNdπYd*0  if (MemError() == noErr && thePrRecHdl != nil)°dONLNdÍcn1*
  4242.     {°dONLNdmxc*
  4243.       PrOpen();°dONLNdÅå©*      if (PrError() == noErr)°dONLNdãñE*
  4244.             {°dONLNd(ï†T*
  4245.          /**°dONLNd5ü™è*
  4246. K              Save the current resource file (i.e. the printer driver's) so°dONLNdÅ©¥º*
  4247. T              the driver will not lose its resources upon return from the pIdleProc.°dONLNd÷≥æY*
  4248.  
  4249.           **/°dONLNd‰Ω»Í*
  4250. *          printmgrsResFile = CurResFile();°dONLNd«“Ã*
  4251. $          PrintDefault(thePrRecHdl);°dONLNd4€ÊΩ*!          if (PrError() == noErr)°dONLNdVÂY*
  4252.  
  4253.             {°dONLNddÔ˙Ô*
  4254. +              if (PrStlDialog(thePrRecHdl))°dONLNdê˘m*
  4255.                 {°dONLNd¢|*
  4256.                  /**°dONLNd∑
  4257. £*
  4258. O                     DetermineNumberOfPagesinDoc determines the number of pages°dONLNd"º*
  4259. T                     contained in the document by comparing the size of the document°dONLNd\!,∑*
  4260. S                     with rPage from the TPrInfo record (IM II-150). It returns the°dONLNd∞+6î*
  4261. L                     number of pages required to print the document for the °dONLNdˇ5`@
  4262. +H
  4263. "       currently selected printer.°dONLNd"?JÅ(f6                  **/°dONLNd8S^v*F                  realNumberOfPagesinDoc = DetermineNumberOfPagesinDoc°dONLNdÅ]hû*
  4264. N                                               ((**thePrRecHdl).prInfo.rPage);°dONLNd–q|*/                  if (PrJobDialog(thePrRecHdl))°dONLNd{ÜÅ*
  4265.                     {°dONLNdÖêê*
  4266.                      /**°dONLNd0èö®*
  4267. P                          Get the number of copies of the document that the user°dONLNdÇô§≠*
  4268. Q                          wants printed from iCopies of the TPrJob record (IM II-°dONLNd÷£ÑÆ∂+l
  4269.  
  4270.      151).°dONLNd·≠∏ï(‘6                      **/°dONLNd˚¡Ãq*E                      numberOfCopies = (**thePrRecHdl).prJob.iCopies;°dONLNdA’‡ö*                       /**°dONLNd\flÍî*
  4271. L                           Get the first and last pages of the document that°dONLNd©ÈÙ≠*
  4272. Q                           were requested to be printed by the user from iFstPage°dONLNd˚Û˛î*
  4273. L                           and iLastPage from the TPrJob record (IM II-151).°dONLNdH˝ü*
  4274.                         **/°dONLNdd]*A                      firstPage = (**thePrRecHdl).prJob.iFstPage;°dONLNd¶&X*
  4275. @                      lastPage = (**thePrRecHdl).prJob.iLstPage;°dONLNdÁ/:ö*                       /**°dONLNd9DN*
  4276. >                           Print "all" pages in the print loop°dONLNdACNü*
  4277.                         **/°dONLNd]Wb5*9                      (**thePrRecHdl).prJob.iFstPage = 1;°dONLNdóalD*
  4278. <                      (**thePrRecHdl).prJob.iLstPage = 9999; ¡4¡˘
  4279. *N6) of 11(÷Z#PR 10 - A Printing Loop That Cares…+YM.PR.PrintLoopˇ*◊#ˇ ˇˇˇˇ#◊ 
  4280. IR,Times
  4281. .+Z-Developer Support Center(-Ê October 1990 /X/,
  4282. Courier
  4283.     °dONLNd'<2æ(NZ                       /**°dONLNd1<<—*
  4284. Q                           Determine the "real" number of pages contained in the °dONLNdo;®FŸ+l
  4285. =     document. Without this test, you would print 9999 pages.°dONLNd≠E<P√(lZ                        **/°dONLNd…Y<dh*<                      if (realNumberOfPagesinDoc < lastPage)°dONLNdc<n^*
  4286. :                        lastPage = realNumberOfPagesinDoc;°dONLNdBw<LJ*T                      PrintingStatusDialog = GetNewDialog(257, nil, (WindowPtr) -1);°dONLNdóã<ñæ*                       /**°dONLNd≤ï<†ï*
  4287. E                           Print the number of copies of the document°dONLNd¯ü<™≥*
  4288. K                           requested by the user from the Print Job Dialog.°dONLNdD©<¥√*
  4289.                         **/°dONLNd`≥<æÆ*
  4290. J                      for (copies = 1; copies <= numberOfCopies; copies++)°dONLNd´Ω<»π*
  4291.                         {°dONLNd≈«<“»*
  4292.                          /**°dONLNd‚—<‹¬*
  4293. N                             Install a pointer to your pIdle proc in my print °dONLNd5€ÃÊÙ+ê
  4294.  record.°dONLNd>Â<Õ( Z                          **/°dONLNd\Ô<˙h*
  4295. <                          (**thePrRecHdl).prJob.pIdleProc = °dONLNdû˘®C+l
  4296.       checkMyPrintDialogButton;°dONLNdæ
  4297. <»(4Z                         /**°dONLNd€<"«*
  4298. O                             Restore the resource file to the printer driver's.°dONLNd+!<,Õ*
  4299.                           **/°dONLNdI5<@O*7                          UseResFile(printmgrsResFile);°dONLNdÅ?<Jü*
  4300. G                          thePrPort = PrOpenDoc(thePrRecHdl, nil, nil);°dONLNd…S<^1*1                          if (PrError() == noErr)°dONLNd˚]<hÕ*
  4301.                             {°dONLNdq<|‹*                              /**°dONLNd:{<Ü©*
  4302. I                                 Print the range of pages of the document°dONLNdÖÖ<ê—*
  4303. Q                                 requested by the user from the Print Job Dialog.°dONLNd◊è<ö·*
  4304. !                              **/°dONLNd˘ô<§E*
  4305. 5                              pageNumber = firstPage;°dONLNd/£<Æ÷*
  4306. R                              while (pageNumber <= lastPage && PrError() == noErr)°dONLNdÇ≠<∏·*
  4307. !                                {°dONLNd§∑<¬m*
  4308. =                                  PrOpenPage(thePrPort, nil);°dONLNd‚À<÷Y*9                                  if (PrError() == noErr)°dONLNd’<‡ı*
  4309. %                                    {°dONLNdCfl<Í*
  4310. (                                     /**°dONLNdlÈ<ÙÃ*
  4311. P                                         rPage (IM II-150) is the printable area°dONLNdΩÛ<˛Ã*
  4312. P                                         for the currently selected printer. By °dONLNd˝¬+¥
  4313. *     passing the current port to the draw °dONLNdB€*
  4314. /     routine, enables your app to use the same °dONLNdv«*
  4315. +     routine to draw to the screen and the °dONLNd¶&h*
  4316.      printer's GrafPort.°dONLNdø%<0    (LZ)                                      **/°dONLNdÈ/<:¬*
  4317. N                                      DrawStuff ((**thePrRecHdl).prInfo.rPage,°dONLNd    99<D÷*
  4318. R                                                 (GrafPtr) thePrPort, pageNumber);°dONLNd    åC<Nı*
  4319. %                                    }°dONLNd    ≤W<bY*9                                  PrClosePage(thePrPort);°dONLNd    Ïa<l'*
  4320. /                                  pageNumber++;°dONLNd
  4321. k<v|*
  4322. @                                }  /**  End pageNumber loop  **/°dONLNd
  4323. ]u<ÄÕ*
  4324.                             }°dONLNd
  4325. {<ä,*
  4326. 0                          PrCloseDoc(thePrPort);°dONLNd
  4327. ¨â<î;*
  4328. 3                        } /**  End copies loop  **/ ¡X¡
  4329. *&#PR 10 - A Printing Loop That Cares…(÷ˇ7) of 11(ÏZM.PR.PrintLoopˇû◊#ˇ ˇˇˇˇ#◊ 
  4330. IR,Times
  4331. .+6-Macintosh Technical Notes /4/˘,
  4332. Courier
  4333.     °dONLNd(Å*                    }°dONLNd'2Ü*
  4334.                    /**°dONLNd-1<£*
  4335. O                       The printing job is being canceled by the request of the°dONLNd};F®*
  4336. P                       user from the Print Style Dialog or the Print Job Dialog.°dONLNdŒEP≤*
  4337. R                       PrError will be set to PrAbort to tell the Print Manager to°dONLNd!OZ&*
  4338. 6                       abort the current printing job.°dONLNdXYdã*
  4339.                     **/°dONLNdpcnÜ*
  4340.                   else°dONLNdámx≠*
  4341. Q                    PrSetError (iPrAbort);   /**  cancel from the job dialog  **/°dONLNdŸwÇm*
  4342.                 }°dONLNdÎÅår*
  4343.               else°dONLNd˛ãñ£*
  4344. O                PrSetError (iPrAbort);   /**  cancel from the style dialog  **/°dONLNdOï†Y*
  4345.  
  4346.             }°dONLNd]ü™E*
  4347.             }°dONLNdg≥æ≤*R      if (((**thePrRecHdl).prJob.bJDocLoop == bSpoolLoop) && (PrError() == noErr))°dONLNd∫Ω»:*
  4348. :        PrPicFile(thePrRecHdl, nil, nil, nil, &theStatus);°dONLNdı—‹J*
  4349.        /**°dONLNd€Êq*
  4350. E           Grab the printing error before you close the Print Manager°dONLNdFÂÃ*
  4351. $           and the error disappears.°dONLNdkÔ˙O*
  4352.         **/°dONLNdw©*      PrintError = PrError();°dONLNdï"h*      PrClose();°dONLNd¶+6J*
  4353.        /**°dONLNd±5@û*
  4354. N           You do not want to report any printing errors until you have fallen°dONLNd?J£*
  4355. O           through the printing loop. This will make sure that ALL of the Print°dONLNdPITô*
  4356. M           Manager's open calls have their corresponding close calls, thereby°dONLNdûS^û*
  4357. N           enabling the Print Manager to close properly and that all temporary°dONLNdÌ]hÔ*
  4358. +           memory allocations are released.°dONLNdgrO*
  4359.         **/°dONLNd%q|Æ*
  4360.       if (PrintError != noErr)°dONLNdE{܇*
  4361. (        PostPrintingErrors (PrintError);°dONLNdnÖê1*
  4362.     }°dONLNdtô§ï*  if (thePrRecHdl != nil)°dONLNd飯€*
  4363. '    DisposHandle((Handle) thePrRecHdl);°dONLNd∂∑¬¬*"  if (PrintingStatusDialog != nil)°dONLNdŸ¡À*
  4364. '    DisposDialog(PrintingStatusDialog);°dONLNd’‡w*  SetPort(oldPort);°dONLNdflÍÅ*
  4365. }  /** PrintStuff **/
  4366. °dONLNd+#*&%Checking And Handling Printing Errors
  4367. °dONLNdQ)•*RAn application should always check for error conditions while printing by calling °dONLNd£•(÷(E√PrError°dONLNd™÷)⁄)1.°dONLNd≠)5I(R6PrError°dONLNd¥*I6©)1 returns errors from °dONLNd…*©6⁄)`<the Printing Manager (and some AppleTalk and OS errors) that°dONLNd6BÄ(^6occur during printing.°dONLNdO[Δ*"As the example code demonstrates, °dONLNd?OΔ[H)Æan application should call °dONLNdZNHZy)ÇPrError°dONLNdaOy[⁄)1 after each call to a°dONLNdw\h_(Ñ6BPrinting Manager function or procedure.  By consistently checking °dONLNdπ[_gê(Ñ}PrError°dONLNd¿\êhΔ)1  after each °dONLNdÃ\Δh⁄)6call,°dONLNd“ht’(ê6`the application is able to catch any errors created at print time and report them to a user via °dONLNd2h’t⁄(êÛa°dONLNd4tć(ú6*dialog box in a clean and graceful manner. ¡4¡˘
  4368. *:8) of 11(÷Z#PR 10 - A Printing Loop That Cares…+YM.PR.PrintLoopˇD◊#ˇ ˇˇˇˇ#◊ 
  4369. IR,Times
  4370. .+Z-Developer Support Center(-Ê October 1990 /X/
  4371. °dONLNd<)ä(EZFThe following section outlines some general error-handling guidelines.°dONLNdG6NBR+•°dONLNdI6[B‹)
  4372. You should avoid calling ,
  4373. Courier°dONLNdb5‹A
  4374. )ÅPrError°dONLNdi6
  4375. B5)1 within °dONLNdq65B⁄)(!your pIdle procedure; errors that°dONLNdìB[N(jy(occur while it is executing are usually °dONLNdªBN⁄)¥*temporary and serve only as internal flags°dONLNdÊN[Z(vy%for communication within the printer °dONLNd NZ⁄)ø$driver—they are not intended for the°dONLNd0[[g(Éy*application.  If you absolutely must call °dONLNdZZfP)ƒPrError°dONLNda[Pgv)1 within °dONLNdi[vg⁄)&your idle procedure,°dONLNd~g[sø(èyLand an error occurs, never abort printing within the idle procedure itself. °dONLNd gøs⁄(è› Wait°dONLNd–s[µ(õyuntil the last called °dONLNdÊsµ⁄)Z@printing procedure returns, then check to see if the error still°dONLNd'[ãË(ßyremains.  Attempting to abort °dONLNdEËã⁄)ç3printing within an idle procedure is a guarantee of°dONLNdyã[óö(≥ycertain death.°dONLNdà£NØR(Àl•°dONLNdä£[Ø¥)
  4376. Upon detecting an °dONLNdú£¥Ø⁄)Y>error after the completion of a printing routine, stop drawing°dONLNd€Ø[ª±(◊yat that point, and °dONLNdÓØ±ª⁄)V:proceed to the next procedure to close any previously made°dONLNd)º[»ë(‰y open calls. °dONLNd5ºë»)63 For example, if you detect an error after calling °dONLNdhª«æ)Ó    PrOpenDoc°dONLNdqºæ»⁄)?, skip°dONLNdx…[’g(Òyto °dONLNd{…g’ë)     the next °dONLNdÑ»ë‘◊)*
  4377. PrCloseDoc°dONLNdé…◊’ê)F).  Or, if you get an error after calling °dONLNd∑»ê‘÷)π
  4378. PrOpenPage°dONLNd¡…÷’⁄)F,°dONLNd√÷[‚¶(˛yskip to the next °dONLNd‘’¶·Û)K PrClosePage°dONLNdfl÷Û‚
  4379. )M and °dONLNd‰’
  4380. ·P)
  4381. PrCloseDoc°dONLNdÓ÷P‚Æ)F.  Remember that if °dONLNd÷Æ‚⁄)^you have°dONLNd „[Ôz( ycalled °dONLNd‚zÓ§)PrOpen°dONLNd„§Ôc)*', then you must call the corresponding °dONLNd?‚cÓî)øPrClose°dONLNdF„îÔ•)1 to °dONLNdJ„•Ô⁄) ensure that°dONLNdVÔ[˚T(y2printing closes properly and all temporary memory °dONLNdàÔT˚⁄)˘allocations are released and°dONLNd•˚[º(#yreturned to the heap.°dONLNdªNR(;l•°dONLNdΩ[^)
  4382. 6Do not display any alert or dialog boxes to report an °dONLNdÛ^⁄(;|error until the end of the°dONLNd[+Õ(Gyprinting loop.  Once at °dONLNd&Õ+⁄)r8the end, check for the error again; if there is no error°dONLNd_+[7Ñ(Sy@assume that printing completed normally.  If the error is still °dONLNdü+Ñ7⁄(S¢present, then you°dONLNd±7[CÆ(_ycan alert the user.°dONLNdΔO[[ª*MThis technique is important for two reasons.  First, if you display a dialog °dONLNdOª[⁄(wŸbox in°dONLNd[[gœ(ÉyJthe middle of the printing loop, it could cause errors that can terminate °dONLNdd[œg⁄(ÉÌan°dONLNdgg[sQ(èy3otherwise normal job.  For example, if the printer °dONLNdögQs⁄)ˆis an AppleTalk printer, the°dONLNd∑s[¨(õyBconnection can be terminated abnormally since the driver would be °dONLNd˘s¨⁄(õ     unable to°dONLNd[ãÖ(ßyrespond °dONLNd Öã⁄)*Dto AppleTalk requests received from the printer while the dialog box°dONLNdPã[ó(≥y%was waiting for input from the user. °dONLNduãó⁄)º& If the printer does not hear from the°dONLNdúó[£-(øy-Macintosh with a short period of time (e.g., °dONLNd…ó-£⁄)“#30 seconds), it times out, assuming°dONLNdÌ£[Øa(Ày5that the Macintosh is no longer there, which results °dONLNd"£aØ⁄(Àin a prematurely broken°dONLNd:Ø[ªØ(◊yGconnection causing another error to which the application must respond.°dONLNdÉ«[”—*In addition, the driver °dONLNdõ«—”⁄)v0may have already displayed its own dialog box in°dONLNdÔ[flÃ(˚yJresponse to an error.  In this instance, the driver posts an error to let °dONLNd    ”Ãfl⁄(˚Íthe°dONLNd    fl[Î…(yJapplication know that something went wrong and it should abort printing.  °dONLNd    dfl…Î⁄(ÁFor°dONLNd    hÎ[˜∑(yexample, when the °dONLNd    zÎ∑˜⁄)\<LaserWriter driver detects that the Laser Prep version which°dONLNd    ∑˜[Δ(yMhas been downloaded to the LaserWriter is different than that with which the °dONLNd
  4383. ˜Δ⁄(‰user°dONLNd
  4384.     [*(+y0is trying to print, it displays the appropriate °dONLNd
  4385. 9*⁄)œ$dialog box informing the user of the°dONLNd
  4386. ^[¡(7ysituation and giving °dONLNd
  4387. s¡⁄)f:him the option of reinitializing the printer.  If the user°dONLNd
  4388. Æ['á(CyAchooses to cancel printing, the driver posts an error to let the °dONLNd
  4389. Ôá'⁄(C•application know°dONLNd '[3x(Oythat it °dONLNd 'x3⁄)Kneeds to abort, but since the driver has already taken care of the error by°dONLNd T3[?å([y?displaying a dialog box, the error is reset to zero before the °dONLNd ì3å?⁄([™printing loop is°dONLNd §?[KÃ(gyJcomplete.  The application should check for the error again at the end of °dONLNd Ó?ÃK⁄(gÍthe°dONLNd ÚK[WC(sy7printing loop, and if it still indicates an error, the °dONLNd )KCW⁄)Ë application can then display the°dONLNd JW[c…(yappropriate dialog box. ¡X¡
  4390. (÷Z#PR 10 - A Printing Loop That Cares…(÷ˇ9) of 11(ÏZM.PR.PrintLoopˇÃ◊#ˇ ˇˇˇˇ#◊ 
  4391. IR,Times
  4392. .+6-Macintosh Technical Notes /4/˘
  4393. °dONLNd**6.+%•°dONLNd*76m)
  4394.     If using ,
  4395. Courier°dONLNd )m5¨)6    PrGeneral°dONLNd*¨6∂)?., be prepared to receive the following errors:°dONLNdD67Bv(_U    NoSuchRsl°dONLNdM7vCÅ)?, °dONLNdO6ÅB¿)     OpNotImpl°dONLNdX7¿C„)?, and °dONLNd^6„B0)# resNotFound°dONLNdi70CÉ)M.  In all three °dONLNdy7ÉC∂)S
  4396. cases, the°dONLNdÑC7Oû(kUapplication should be °dONLNdöCûO∂)g;prepared to continue to print without using the features of°dONLNd÷O7[†(wUthat particular opcode.°dONLNdÔh7t¬*However, in the case of the °dONLNd g¬s)ã resNotFound°dONLNdht^)M error, it means °dONLNd'h^t∂)Othe current printer°dONLNd;u7Å∞(ùUdriver does not support °dONLNdSt∞ÄÔ)y    PrGeneral°dONLNd\uÔņ)?#.  This lack of support should not °dONLNdu†Å∂)±be a°dONLNdÑÅ7ç9(©U8problem for an application, but it needs to be prepared °dONLNdºÅ9ç∂(©Wto deal with this error.  If°dONLNdŸé7öx(∂Uyou receive a °dONLNdÁçxô≈)A resNotFound°dONLNdÚé≈ö¸)M  error from °dONLNd˛ç¸ô-)7PrError°dONLNdé-öê)1, clear the error with °dONLNdéêö∂)c    a call to°dONLNd&ö7¶í(√U
  4397. PrSetError(0)°dONLNd3õíßœ)[
  4398. ; otherwise, °dONLNd@öœ¶)=PrError°dONLNdGõßs)1 might still contain this °dONLNdaõsß∂)serror the next°dONLNdpß7≥á(œUFtime you check it, which would prevent your application from printing.
  4399. °dONLNd∑À⁄1(ˆ6)Canceling or Pausing the Printing Process
  4400. °dONLNd·ÊÚë*If you install a procedure °dONLNd¸ÊëÚ⁄)yEfor handling requests to cancel printing, with an option to pause the°dONLNdBÚ˛(6-printing process, beware of timeout problems °dONLNdoÚ˛⁄(:!when printing to the LaserWriter.°dONLNdí˛
  4401. W(&6=Communication between the Macintosh and the LaserWriter must °dONLNdœ˛W
  4402. ⁄(&ube maintained to prevent a°dONLNdÍ
  4403. Ã(26^job or a wait timeout.  If there is no communication for a period of time (over two minutes), °dONLNdH
  4404. Ã⁄(2Íthe°dONLNdL"°(>6Yprinter times out and the print job terminates due to a wait  timeout.  Or, if the print °dONLNd•°"⁄(>ø job requires°dONLNd≤".µ(J6"more than three minutes to print, °dONLNd‘"µ.⁄)ù?the print job terminates due to a job timeout.  Since, there is°dONLNd.:Ô(V6,no good method to determine to what type of °dONLNd@.Ô:⁄)◊4printer an application is printing, it is probably a°dONLNdu:Få(b6Mgood idea to document the possibility of a LaserWriter timing out for a user °dONLNd¬:åF⁄(b™who chooses to°dONLNd—FRƒ(n6$select “pause” for over two minutes.
  4405. °dONLNdˆjy'*'%Error Messages Created In Print Land…
  4406. °dONLNdÖë*0The Printing Manager reports the error messages °dONLNdLÖë⁄)È/covered in this section.  If an error that does°dONLNd|ëùO(π6 not belong °dONLNdáëOù⁄)7Mto the Printing Manager occurs, the Printing Manager puts it into low memory,°dONLNd’û™Ë(Δ6)where it can be retrieved with a call to °dONLNd˛ùË©)–PrError°dONLNdû™#)1, °dONLNdû#™⁄)
  4407. $and terminates the printing loop, if°dONLNd,™∂#(“67necessary.  As already documented, if you encounter an °dONLNdc™#∂⁄(“A'error in the middle of a printing loop,°dONLNdã∂¬Æ(fi6Wdo not jump out; fall through the loop and let the Printing Manager terminate properly.°dONLNd„Œ<⁄{+$
  4408. Error Code°dONLNdÓŒÑ⁄∂)HConstant°dONLNd˜Œ⁄1)l Description ˘X˘ñ°dONLNd‹ZË`(x0°dONLNd€ÑÁß)*noErr°dONLNd ‹Ë)lNo error°dONLNdÈNı`(l128°dONLNdËÑÙº)6iPrAbort°dONLNd#Èık)lAbort the printing process°dONLNdBıK* (Command-period)°dONLNdTV`(*t-1°dONLNdWÑ
  4409. —). iPrSavePFil°dONLNdce)lProblem saving print file°dONLNd~P`(7n-17°dONLNdÇÑ )4
  4410. controlErr°dONLNdçu)lUnimplemented Control call°dONLNd©P(`(Dn-27°dONLNd≠Ñ'º)4iIOAbort°dONLNd∂(.)l I/O problems°dONLNdƒ)J5`(Qh-108°dONLNd…(Ñ4—): iMemFullErr°dONLNd’)5^)lNot enough heap space TXTñ ¡4¡˘
  4411. (÷610)
  4412.  of 11(÷Z#PR 10 - A Printing Loop That Cares…+YM.PR.PrintLoopˇ÷◊#ˇ ˇˇˇˇ#◊ 
  4413. IR,Times
  4414. .+Z-Developer Support Center(-Ê October 1990 /X/
  4415. °dONLNd)<5R(QZ<The following errors are specific to the LaserWriter family:°dONLNd>BhNÑ+,-4101°dONLNdEBNì)¨Printer not found or closed `|`°dONLNdbNhZÑ(vÜ-4100°dONLNdiNZ)¨Connection just closed°dONLNdÅZhfÑ(ÇÜ-4099°dONLNdàZfw)¨Write request too big°dONLNdüfhrÑ(éÜ-4098°dONLNd¶fr})¨Request already active°dONLNdærh~Ñ(öÜ-4097°dONLNd≈r~Ç)¨Bad connection refnum°dONLNd‹~häÑ(¶Ü-4096°dONLNd„~ä¨)¨No free Connect Control     °dONLNd˚~¨ä˛)ò
  4416. Blocks (CCBs)°dONLNd    äñ=(≤2    available°dONLNdñh¢Ñ(æÜ-8133°dONLNdñ¢Ù)¨.PostScript error occurred during transmission °dONLNdIñÙ¢˛)‡of°dONLNdL¢Æ( 20data to printer.  Most often caused by a bug in °dONLNd|¢Æ˛)‹the°dONLNdÄÆ∫º(÷2!PostScript code being downloaded.°dONLNd£∫hΔÑ(‚Ü-8132°dONLNd™∫Δp)¨Timeout occurred. °dONLNdº∫pΔ˛)\ This error is returned when°dONLNdŸΔ“U(Ó2 no data has °dONLNdÂΔU“˛)A been sent to the printer for two°dONLNd“fiw(˙2minutes.  Usually °dONLNd“wfi˛)ccaused by extremely long°dONLNd1fiÍU(2
  4417. imaging time.°dONLNd@ÍhˆÑ(Ü-8131°dONLNdG͈7)¨Printer °dONLNdOÍ7ˆ˛)#(not responding:  it may have been turned°dONLNdxˆQ(2
  4418. “off.”  This °dONLNdÖˆQ˛)=$error occurs if a user turns off the°dONLNd™–(*2)LaserWriter in the middle of a print job. -|-°dONLNd‘(<4Â(PZ%The following errors are specific to ,
  4419. Courier°dONLNd˘'Â3$)©    PrGeneral°dONLNd($4')?:°dONLNdB~NÑ(jú1°dONLNdA®MÁ)*    NoSuchRsl°dONLNdBNΔ)l%Requested resolution is not supported _|_˝°dONLNd8O~[Ñ(wú2°dONLNd:N®ZÁ)*    OpNotImpl
  4420. °dONLNdDO[R)l
  4421. Requested  °dONLNdNNRZë)>    PrGeneral°dONLNdWOë[fi)?  opcode not°dONLNdc[g÷(É2*implemented in the current printer driver.°dONLNdèhntÑ(êå-192°dONLNdîg®sı): resNotfound°dONLNd†htß)l The current printer driver does °dONLNd¿hßtfi)ì not support°dONLNdÃtÄS(ù2    PrGeneral°dONLNd’uSÅW)?. †|†˝°dONLNd◊ö<¶’(¬ZTThe most common error encountered is -4101, which is generated if no LaserWriter is °dONLNd+ö’¶˛(¬Û    selected.°dONLNd6¶<≤†(ŒZSince this error is so °dONLNdM¶†≤˛)dHcommon, it is a good idea to display a dialog box requesting the user to°dONLNdñ≤<æl(⁄ZAselect a printer from the Chooser when this error is encountered.°dONLNdÿ‚<Ó¶*0Further Reference: 
  4422. X
  4423. °dONLNdÎÔN˚R+
  4424. •°dONLNdÌÔ`˚±)Inside Macintosh°dONLNd˝Ô±˚ô)Q-, Volume II-145 & V-410, The Printing Manager°dONLNd+˚NR(#l•°dONLNd-˚`")$Technical Note M.IM.DevIndPrinting —°dONLNdTÑ+$  Device-Independent Printing°dONLNdqNR(;l•°dONLNds`ó)
  4425. d e v e l o p°dONLNdÄóQ)7&, July 1990, Issue 3, “Meet PrGeneral” ¡X¡
  4426. (÷Z#PR 10 - A Printing Loop That Cares…(÷˙11)
  4427.  of 11(ÏZM.PR.PrintLoopˇ‰◊#ˇ ˇˇˇˇ#◊†Ç 
  4428. /ZÅ1
  4429.     0Ià:µú9"{(    ˇˇˇˇˇˇˇˇ#†ƒ°d
  4430. ONLNf˛†å°d1drw2…-·_ġˇˇˇˇˇè°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˙ó@†ò,Times
  4431. .R◊R…õr+]BNew Technical Notes†ô°ddrw2:°„†ó°d1drw2eÙġˇˇˇˇˇP°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚ÄE¿†ò
  4432. *K({üDeveloper Support†ô°ddrw2:°„†ó°d`drw2-ÔˇˇˇˇˇˇKÔ- Z  f*fZ°d1drw2 ¿˙ÈˇˇˇˇˇˇK°ñ x°ddrw2:°ddrw2:$°d4drw2:0°öˇÙĆò
  4433. 0Ï(U˚†ô°ddrw2:°„†ó°d1drw2ÔÊ˙ˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:    °öˇ˝Ä†ò
  4434.      +(    ®†ô°ddrw2:°„†ó°d1drw2Â-¯yˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚Ä%†ò
  4435. ìõ(Z\    Macintosh†ô°ddrw2:°„†ó†ç°ddrw2D†É
  4436. IR.°dONLNdn<Å{(õZ%PR 11 - Programmatic PostScript Files
  4437. °dONLNd&Ä<ès*Printing
  4438. °dONLNd0õ<ßq* Written by:°dONLNd<õÑß)HMatt Deatherage & Hugo Ayala°dONLNdYõ√ß(√·September 1992°dONLNdh≥<ø°(€ZThis Technical Note °dONLNd|≥°ø˛)eEdiscusses how to make the LaserWriter driver, versions 7.0 and later,°dONLNd¬ø<À÷(ÁZYcreate PostScript files from your printing loop, and when this is and is not appropriate.°dONLNd◊<„b*Topics°dONLNd#„WÔ—+ • Creating PostScript files°dONLNd?ÔW˚x* ?• The LaserWriter driver is not a PostScript conversion utility°dONLNd˚Wi* ;• Sample functions for creating an appropriate print record 2X2
  4439. °dONLNdª,<;(WZI get to make PostScript files?
  4440. °dONLNd€G<SÊ*$Yes, but don’t get too excited yet. °dONLNdˇGÊS˛)™9 The feature we’re about to describe is not applicable in°dONLNd9S<_£({ZIevery case where you might want to generate PostScript code, so it’s not °dONLNdÇS£_˛({¡a generic solution.°dONLNdó_<kÒ(áZ&Like those standardized tests used to °dONLNdΩ_Òk˛)µ7say, “Please read all the directions before marking the°dONLNdık<w[(ìZpage.”°dONLNd¸É<èØ*OThere are definitely situations where forcing the LaserWriter driver to create °dONLNdKÉØè˛(´Õa PostScript file°dONLNd]è<õ    (∑Z*has advantages.  It’s extremely handy for °dONLNdáè    õ˛)Õ1many large, multi-network Macintosh installations°dONLNdπõ<ßÅ(√ZCthat have unique printing needs.  It can be handy for people using °dONLNd¸õÅ߲(√ünon-AppleTalk PostScript°dONLNdß<≥û(œZPprinters.  It’s a very useful capability in this and dozens of other situations.°dONLNdfø<Àj*
  4441. What it’s °dONLNdpøjÀ|).not°dONLNdsø|ÀL)- useful for is generic PostScript conversion.°dONLNd°◊<„/(ˇZ2The LaserWriter driver was designed expressly for °dONLNd”◊/„˛)Û)the purpose of converting QuickDraw calls°dONLNd˝„<Ô†( ZJto PostScript for high-resolution imaging on Apple’s PostScript printers. °dONLNdG„†Ô˛( æ As the years have°dONLNdZÔ<˚7(Z7gone by, it’s been adapted to things that weren’t part °dONLNdëÔ7˚˛)˚*of the original design model (like driving°dONLNdº˚<^(#Z>non-Apple PostScript printers).  One of the features added in °dONLNd˙˚^˛(#|"recent years was the capability to°dONLNd<+(/Z0dump a PostScript file when printing.  This was °dONLNdM+˛)Ô+originally only a debugging feature for the°dONLNdy<(;Z,convenience of the engineers working on the °dONLNd•˛)÷0driver, but when it was made accessible to users°dONLNd÷<+Ú(GZ!through a hidden dialog item and °dONLNd˜Ú+˛)∂1a not-so-secret key combination, the response was°dONLNd)+<7\(SZ<overwhelming.  In response, the printing engineers included °dONLNde+\7˛(Sz#the capability to pick a PostScript°dONLNdâ7<Cj(_ZDfile for output was built into versions 7.0 and later of the driver.°dONLNdŒO<[‹*!That didn’t change the fact that °dONLNdÔO‹[˛)†;it was still, at heart, a glorified debugging feature.  The°dONLNd+[<gé(ÉZKPostScript the driver creates is designed expressly for printing.  It does °dONLNdv[ég˛(ɨnot create Encapsulated°dONLNdég<ss(èZ PostScript °dONLNdôgss˛)7Kfiles (EPSF format).  It doesn’t easily incorporate any PostScript document°dONLNdÂs<N(õZ<conventions other than the one it uses for its own benefit. °dONLNd    !sN˛(õl% It doesn’t generate PostScript Level°dONLNd    G<ãV(ßZ2.  It °dONLNd    NVã˛)Sincludes large amounts of custom encrypted code to provide TrueType™ font rendering°dONLNd    ¢ã<ó((≥Z1technology on PostScript printers where possible. ¡X¡
  4442. *#%PR 11 - Programmatic PostScript Files(÷1) of 6(ÏZM.PR.ProgrammaticPostScriptˇ°¿Ù%%DSIDICT:_cv
  4443. currentdict /bu known {bu}if
  4444. userdict /_cv known not{userdict /_cv 30 dict put}if
  4445. _cv begin
  4446. /bdf{bind def}bind def
  4447. currentscreen/cs exch def/ca exch def/cf exch def
  4448. /setcmykcolor where{/setcmykcolor get /cvcmyk exch def}{/cvcmyk{1 sub 4 1 roll 3{3 index add neg dup 0 lt{pop 0}if 3 1 roll}repeat setrgbcolor pop}bdf }ifelse
  4449. /ss{//cf //ca //cs setscreen}bdf
  4450. /stg{ss setgray}bdf
  4451. /strgb{ss setrgbcolor}bdf
  4452. /stcmyk{ss cvcmyk}bdf
  4453. /min1{dup 0 eq{pop 1}if}bdf
  4454. end
  4455. currentdict /bn known {bn}if
  4456. †ø◊#ˇ ˇˇˇˇ#◊ 
  4457. IR,Times
  4458. .+6-Macintosh Technical Notes /4/˘
  4459. °dONLNd)5â*$MIt’s important to understand that you can’t change any of this.  If you have °dONLNdM)â5⁄(Qßa strong need to°dONLNd^5A´(]6Sprogrammatically create files just like the LaserWriter driver would create if you °dONLNd±5´A⁄(]…    chose the°dONLNdªAMW(i6H“PostScript file” radio button in the job dialog, this technique is for °dONLNdAWM⁄(iuyou.  If you need anything°dONLNdMYy(u6Lmore customizable, or more specialized, or in a different format, this Note °dONLNdjMyY⁄(uóis not for you.  The°dONLNdYeÄ(Å6LaserWriter driver is °dONLNdïYÄe⁄)hFnot and never has been a generic PostScript conversion utility; if you°dONLNd‹eqc(ç6Hwant such capabilities, you must still build them into your application.
  4460. °dONLNd%âòû*'How to Do the Deed
  4461. °dONLNd8§∞’*]The LaserWriter driver stores the PostScript file information in the print record—but not in °dONLNdï§’∞⁄(ÃÛa°dONLNdó∞º©(ÿ6format designed for your easy °dONLNdµ∞©º⁄)ëAaccess.  To make it print to a PostScript file, you have to set a°dONLNd˜Ω…[(Â6bit, fill in a ,
  4462. Courier°dONLNdº[»å)CvRefNum°dONLNd
  4463. Ωå…ß)1 , a °dONLNdºß» )dirID°dONLNdΩ …Ú)# and a °dONLNdΩÚ…)(pointer°dONLNd%Ω…)! °dONLNd&Ω…⁄)%to the file name—all inside a private°dONLNdL…’ü(Ò6LaserWriter driver structure.°dONLNdj·Ìp*The flag is a bit in °dONLNd·pÌ⁄)XMthe word starting at offset $52 (or 82 decimal) of the print record.  This is°dONLNdÕÓ˙c(6documented as °dONLNd€Óc˙´)Kboolean value °dONLNdÈÌ´˘π)Hf2°dONLNdÎÓπ˙C) of the printer flags record °dONLNdÌC˘t)äprFlag1°dONLNdÓt˙⁄)1.  Figure 1 shows a°dONLNd#˚(#67redeclaration of this record with the newly-documented °dONLNdZ˙P(#=fPSFile°dONLNda˚Pé)1 bit included."23# 242!"2"#"33    "3"    
  4464.     °dONLNdp)©(E6   lwTPrFlag1 = PACKED RECORD"=3    "="    °dONLNdé(3∏*
  4465.                     f15: BOOLEAN;"G3    "G"    °dONLNdØ2=∏*
  4466.                     f14: BOOLEAN;"Q3    "Q"    °dONLNd–<G∏*
  4467.                     f13: BOOLEAN;"[3    "["    °dONLNdÒFQ∏*
  4468.                     f12: BOOLEAN;"e3    "e"    °dONLNdP[∏*
  4469.                     f11: BOOLEAN;"o3    "o"    °dONLNd3Ze∏*
  4470.                     f10: BOOLEAN;"y3    "y"    °dONLNdTdo≥*
  4471.                    f9: BOOLEAN;"É3    "É"    °dONLNdtny≥*
  4472.                    f8: BOOLEAN;"ç3    "ç"    °dONLNdîxÉ≥*
  4473.                    f7: BOOLEAN;"ó3    "ó"    °dONLNd¥Çç≥*
  4474.                    f6: BOOLEAN;"°3    "°"    °dONLNd‘åó≥*
  4475.                    f5: BOOLEAN;"´3    "´"    °dONLNdÙñ°≥*
  4476.                    f4: BOOLEAN;"µ3    "µ"    °dONLNd†´≥*
  4477.                    f3: BOOLEAN;"ø3    "ø"    °dONLNd4™µÃ*
  4478. $                   fPSFile: BOOLEAN;"…3    "…"    °dONLNdY¥ø÷*
  4479. &                   fLstPgFst: BOOLEAN;"”3    "”"    °dONLNdÄæ…€*
  4480. '                   fUserScale: BOOLEAN;"›3    "›"    °dONLNd®»”|*
  4481.                 END;"Á3    "Á"    "˚3# ˚4˚!"˚"#"Ò3    "Ò"    
  4482. °dONLNdΩÈèıb+w"!Figure 1—Redefined PrFlag1 Record°dONLNdfl(66/Note that the record is renamed beginning with °dONLNd
  4483. )lw°dONLNd)) to °dONLNd)¡)emphasize that this technique °dONLNd2¡⁄)òonly°dONLNd7&(B61works with the LaserWriter driver.    This means °dONLNdh&⁄)Í-you have to check that you’re printing to the°dONLNdñ'3S(O6 LaserWriter °dONLNd¢'S3);'driver by making sure the high byte of °dONLNd…&2`)¿ TPRStl.wDev°dONLNd‘'`3⁄)M is 3, for the LaserWriter°dONLNdÔ3?d([6driver.  If other °dONLNd3d?⁄)LKdrivers impersonate the LaserWriter driver (which they may do, for example,°dONLNdM?Kü(g6Jso that your application sends them PostScript in picture comments), this °dONLNdó?üK∂(gΩmay°dONLNdö?∂KΩ) °dONLNdõ?ΩK⁄)crash.°dONLNd£KWq(s6LUnfortunately, Apple can’t conclusively tell you that a third-party printer °dONLNdÔKqW⁄(sèdriver will or will not°dONLNd    Wcfi(6+support this feature.  Apple’s driver does.°dONLNd    3o{ù*RWhere does the LaserWriter driver put the new PostScript file?  The word starting °dONLNd    Öoù{⁄(óª
  4484. at offset $68°dONLNd    ì|àx(§6(104 decimal) is the °dONLNd    ®{xá©)`vRefNum°dONLNd    Ø|©àé)15 for the file to save, and the long at offset $70 is °dONLNd    ‰|éà⁄)Âthe directory ID°dONLNd    ıàîú(∞6for where to store the file.   °dONLNd
  4485. àúî⁄)ÑC The long starting at $6A (or 106 decimal in the print record) is a ¡4¡˘
  4486. (÷62) of 6(÷Y%PR 11 - Programmatic PostScript Files+!M.PR.ProgrammaticPostScriptˇÍ◊#ˇ ˇˇˇˇ#◊ 
  4487. IR,Times
  4488. .+Z-Developer Support Center(-€September 1992 /X/
  4489. °dONLNd<)˙(EZ'pointer to the PostScript file name as °dONLNd'˙)˛)æ4a Pascal string—just the file name; the other fields°dONLNd\)<5›(QZ#indicate the other portions of the °dONLNd)›5˛)°?file’s specification (in fact, they’re all three portions of an,
  4490. Courier°dONLNdø5<Af(^ZFSSpec°dONLNd≈6fBè)*     record).°dONLNdœN<ZÃ(vZTHowever, the name pointer isn’t just any old pointer.  There’s some baggage with it.°dONLNd$f<r©*PFirst, the LaserWriter driver always assumes that it allocated the pointer, and °dONLNdtf©r˛(é«somewhere in the°dONLNdÖs<(õZ'printing loop, when it’s done with the °dONLNd¨sñ)ƒPostScript file name, it calls °dONLNdÀrñ~’)ñ    DisposPtr°dONLNd‘s’˛)? on that°dONLNd›Ä<åµ(®Zpointer.  That means you °dONLNdˆÄµå–)ymust°dONLNd˙Ä–å”) °dONLNd˚Ä”å)allocate it with °dONLNd ãG)JNewPtr°dONLNdÄGåj)* and it °dONLNdÄjåÖ)#must°dONLNdÄÖå˛) be valid during the print°dONLNd9å<ò„(¥Z#loop, or your heap becomes toast.  °dONLNd\å„ò˛)ß:It should be a 64-byte pointer, because the driver assumes°dONLNdóò<§à(¿Zthat’s what it is.°dONLNd™∞<º_*>Second, the LaserWriter driver assumes that it’s the only one °dONLNdË∞_º˛(ÿ}who would be messing with this°dONLNdΩ<…Ò(ÂZ)private field in the print record, so it °dONLNd0ΩÒ…Z)µonly clears it during °dONLNdFºZ»ô)i    PrJobInit°dONLNdOΩô…˛)?.  That means when°dONLNdb…<’ı(ÒZ]you're done printing, your print record will still contain a pointer to the memory that used °dONLNdø…ı’˛(Òto°dONLNd¬’<·Á(˝Z'point to the file name string.  If you °dONLNdÈ’Á·˛)´;save this print record and try to print again without going°dONLNd%·<ÌØ(    Zthrough the job dialog, °dONLNd=·ØÌ˛)sDthe LaserWriter driver will use it as a pointer on your behalf, even°dONLNdÇÓ<˙◊(Z!though it probably doesn’t point °dONLNd£Ó◊˙È)õ9to anything useful anymore.  Also, if the pointer is non-°dONLNd‹ÌÈ˘˛(NIL°dONLNd‡˚<J(#Z5entering the job dialog (if somehow someone bypasses °dONLNd˙Jâ(#h    PrJobInit°dONLNd˚âï)?), °dONLNd!˚ï˛) it also assumes it’s a°dONLNd8<≠(/ZQpointer and uses it.  So, before you save or use this print record for anything, °dONLNdâ≠ÿ(/Àalways °dONLNdêÿ˛)+zero the°dONLNdô<V(;Z<file name pointer.  It will save many hassles down the road.°dONLNd÷,<81*4Third, if you encounter a print record that has the °dONLNd
  4491. +17b)ıfPSFile°dONLNd,b8¡)1 bit (bit 3 of offset °dONLNd',¡8˛)_ $52) already°dONLNd48<D.(`Z2set, the LaserWriter driver has already validated °dONLNdf8.D˛)Ú)the information in the print record.  The°dONLNdêD<P∏(lZpointer has been allocated °dONLNd´D∏PÉ)|*and the directory information stored.  Do °dONLNd’DÉPï)Ànot°dONLNdÿDïP˛) override these values°dONLNdÔP<\€(xZor you may cause a memory leak.°dONLNdi<uø*VThe driver also saves in the print record, in the next two bytes starting at $6E, the °dONLNdehøt(ë›vRefNum°dONLNdliu˛)1 of°dONLNdpu<Åı(ùZdthe last volume used to store a PostScript file.  It also uses the directory ID field at offset $70 °dONLNd‘uıŞ(ùto°dONLNd◊Å<çá(©Zindicate the last °dONLNdÈÅáç˛)KPdirectory used for storing a PostScript file.  This is only so the Standard File°dONLNd:é<öò(∂Zdialog put up by °dONLNdKçòôÂ)\ PrJobDialog°dONLNdVéÂö6)M can start with °dONLNdfé6ö˛)Q(the most appropriate directory; it’s not°dONLNdèö<¶:(¬Z4important to programmatic control of this mechanism.°dONLNdƒ≤<æ≤*PFigure 2 shows the LaserWriter driver’s version of the print record, redeclared °dONLNd    ≤≤æ˙(⁄–with the newly°dONLNd    "≤˙æ˛)H-°dONLNd    #ø<Àø(ÁZdocumented information as °dONLNd    =æø ˛)É    lwTHPrint°dONLNd    Fø˛À)?: ¡X¡
  4492. (÷Z%PR 11 - Programmatic PostScript Files(÷3) of 6(ÏZM.PR.ProgrammaticPostScriptˇ◊#ˇ ˇˇˇˇ#◊ 
  4493. IR,Times
  4494. .+6-Macintosh Technical Notes /4/˘"<3# <4<Ã"<Õ#"=3    "=Õ    ,
  4495. Courier
  4496.     °dONLNd(3,*"TYPE"G3    "GÕ    °dONLNd2=:*
  4497. :   { Print Job: Print "form" for a single print request. }"Q3    "QÕ    °dONLNd@<Gï*
  4498.    lwTPPrint = ^lwTPrint;"[3    "[Õ    °dONLNdZFQö*
  4499.    lwTHPrint = ^lwTPPrint;"e3    "eÕ    °dONLNduP[|*
  4500.    lwTPrint = RECORD"o3    "oÕ    °dONLNdäZeq*
  4501. E                 iPrVersion: INTEGER; {(2) Printing software version}"y3    "yÕ    °dONLNd–doè*
  4502. K                 prInfo: TPrInfo; {(14) the PrInfo data associated with the"É3    "ÉÕ    °dONLNdny*
  4503. 2                                   current style.}"ç3    "çÕ    °dONLNdOxÉî*
  4504. L                 rPaper: Rect; {(8) The paper rectangle [offset from rPage]}"ó3    "óÕ    °dONLNdúÇç]*
  4505. A                 prStl: TPrStl; {(8) This print request's style.}"°3    "°Õ    °dONLNdfiåóq*
  4506. E                 prInfoPT: TPrInfo; {(14) Print Time Imaging metrics}"´3    "´Õ    °dONLNd$ñ°ä*
  4507. J                 prXInfo: TPrXInfo; {(16) Print-time (expanded) Print info"µ3    "µÕ    °dONLNdo†´˘*
  4508. -                                     record.}"ø3    "øÕ    °dONLNdù™µô*
  4509. M                 prJob: TPrJob; {(20) The Print Job request (82) Total of the"…3    "…Õ    °dONLNdÎ¥øô*
  4510. M                                 above; 120-82 = 38 bytes needed to fill 120}"”3    "”Õ    °dONLNd9æ…∏*
  4511.                   CASE INTEGER OF"›3    "›Õ    °dONLNdZ»”Ü*
  4512.                     0:"Á3    "ÁÕ    °dONLNdq“›:*
  4513. :                       (printX: ARRAY [1..19] OF INTEGER);"Ò3    "ÒÕ    °dONLNd¨‹ÁÜ*
  4514.                     1:"˚3    "˚Õ    °dONLNd√ÊÒD*
  4515. <                       (prFlag1: TPrFlag1; {a word of flags}"3    "Õ    °dONLNd˚Í*
  4516. *                        iZoomMin: INTEGER;"3    "Õ    °dONLNd+˙Í*
  4517. *                        iZoomMax: INTEGER;"3    "Õ    °dONLNdVä*
  4518. J                        hDocName: StringHandle; {current doc's name, nil ="#3    "#Õ    °dONLNd°N*
  4519. >                                                 front window}"-3    "-Õ    °dONLNd‡#q*
  4520. E                        reservedAndWeMeanIt: ARRAY [1..6] OF INTEGER;"73    "7Õ    °dONLNd&"-*
  4521. /                        psFileVRefNum: INTEGER;"A3    "AÕ    °dONLNdV,7Â*
  4522. )                        pPSFileName: Ptr;"K3    "KÕ    °dONLNdÄ6A˘*
  4523. -                        lastVRefNum: INTEGER;"U3    "UÕ    °dONLNdÆ@K˛*
  4524. .                        lastDirID: Longint; );"_3    "_Õ    °dONLNd›JUr*
  4525.               END;"i3    "iÕ    "}3# }4}Ã"}Õ#"s3    "sÕ    
  4526. °dONLNdkòwZ+Ä"Figure 2—Redefined Print Record°dONLNdÉè8(´6When °dONLNdÉ8è⁄) Uyou print in the foreground, the LaserWriter driver uses the information in the print°dONLNdkèõ¡(∑6'record to create the PostScript file.  °dONLNdíè¡õ⁄)©8When you print in the background, the LaserWriter driver°dONLNdÀõß1(√6adds °dONLNd–õ1ß⁄)Xa resource with the information to the spool file so PrintMonitor can do the same thing.°dONLNd*ß≥r(œ6GThis lets this method work in both the foreground and background cases.°dONLNdrøÀK* Be careful °dONLNd}øKÀ⁄)3Pabout picking file names to use—whatever method you use, if the file name is not°dONLNdŒÀ◊ø(Û6Zunique, the LaserWriter driver will attempt to delete the existing file and cause you, as °dONLNd(Àø◊⁄(Û›Hugo°dONLNd-◊„Ø(ˇ6Xputs it, “endless grief.”  Simply examining the directory at spooling time isn’t enough °dONLNdÖ◊Ø„⁄(ˇÕ
  4527. if there’s°dONLNdê„Ôb( 6Dany chance the file name might not be unique when PrintMonitor gets °dONLNd‘„bÔ⁄( Äaround to despooling the°dONLNdÌÔ˚3(6file.  °dONLNdÙÔ3˚⁄)WFurthermore, if you try to write over an existing file, the LaserWriter driver will not°dONLNd    L˚M(#6 change the °dONLNd    W˚M⁄)5Uend-of-file position, so the result file will have the larger EOF of the new file and°dONLNd    ≠º(/6$the old contents.  This is also Bad.°dONLNd    “+Í*)Here’s a summary of what we’ve discussed: ¡4¡˘
  4528. *è4) of 6(÷Y%PR 11 - Programmatic PostScript Files+!M.PR.ProgrammaticPostScriptˇ¨◊#ˇ ˇˇˇˇ#◊ 
  4529. IR,Times
  4530. .+Z-Developer Support Center(-€September 1992 /X/
  4531. °dONLNd<)F(EZ1.°dONLNdN)>)5Get a print record ready to start your printing loop.°dONLNd9*<6F(RZ2.°dONLNd<*N6Ü) Change the ,
  4532. Courier°dONLNdG)Ü5∑)8fPSFile°dONLNdN*∑6Ó)1H bit to tell the LaserWriter driver to create a PostScript file instead.°dONLNdó7<CF(_Z3.°dONLNdö7NCq)Set the °dONLNd¢6qB¢)#vRefNum°dONLNd©7¢Cü)17 and directory ID for where you want to store the file.°dONLNd·C<OI(kZ4. °dONLNdÂCNOD)7Allocate a 64-byte pointer to store the file name; put °dONLNdCDO˛)ˆ$the filename in the new memory block°dONLNdAON[(wl(and put the pointer in the print record.°dONLNdj[<gF(ÉZ5.°dONLNdm[Ng˙)#Complete your print loop as normal.°dONLNdëg<sF(èZ6.°dONLNdîgNsk)?Zero the file name pointer in the print record as a precaution.°dONLNd‘s<F(õZ7.°dONLNd◊sNk)=Save or otherwise manipulate the print record for future use.
  4533. °dONLNdó<¶•(¬ZSamples?  Sure.
  4534. °dONLNd%≥<ø*+The following System 7-only sample routine °dONLNdP≤æÄ)‚PrPSFileDialog°dONLNd^≥Äøö)b can °dONLNdc≥öø˛)be used in place of°dONLNdwø<Àâ(ËZ PrJobDialog°dONLNdÇ¿âÃ)M when using this technique.  °dONLNdü¿Ã˛)é/Note that the routine requires a handle of type°dONLNdœÃ<ÿ{(ıZ    lwTHPrint°dONLNdÿÕ{Ÿ)?.°dONLNd⁄Â<Ò[(
  4535. ZNote:°dONLNd‡Â`ÒÙ)$Be careful about bypassing the °dONLNdˇÂÙÒ⁄)î/job dialog.  The LaserWriter driver resets some°dONLNd/Ò`˝(~other °dONLNd5Ò˝⁄)Cjob-specific parameters (besides the file to save PostScript in) in°dONLNdy˝`    ü(&~    PrJobMain°dONLNdDzü
  4536. µ)?.  °dONLNdÖ˛µ
  4537. ⁄)4If you save a print record immediately after calling°dONLNd∫
  4538. `≠(3~ PrJobDialog°dONLNd≈ ≠◊)M     and use °dONLNdŒ ◊⁄)*6that print record without going through the job dialog°dONLNd`#Å(?~again, °dONLNd Å#è)!all°dONLNdè#|)2 of the job-specific parameters will be preserved °dONLNdA|#⁄)Ì(number of copies,°dONLNdT#`/®(K~Epage range, feeder choice, etc.).  This may not be what you intended.
  4539.     °dONLNdö;<FY(bZ9FUNCTION PrPSFileDialog(thePrRecHdl: lwTHPrint): BOOLEAN;°dONLNd‘Q<\Z*   VAR°dONLNd€[<fÊ*
  4540. "      ourReply: StandardFileReply;°dONLNd˛e<pπ*
  4541.       tempFlags: INTEGER;°dONLNdo<zæ*
  4542.       tempResult: BOOLEAN;°dONLNd3y<Ñ¥*
  4543.       ourOSError: OSErr;°dONLNdLÉ<éõ*
  4544.       tempPtr: Ptr;°dONLNd`ó<¢d*   BEGIN°dONLNdi°<¨E*
  4545. 5      PrPSFileDialog := FALSE; { being conservative }°dONLNdü´<∂E*
  4546. 5      tempResult := PrValidate(THPrint(thePrRecHdl));°dONLNd’ø< '*/      IF NOT thePrRecHdl^^.prFlag1.fPSFile THEN°dONLNd…<‘r*
  4547. >      { don't do this if there's already a file to be saved! }°dONLNdD”<fiÇ*
  4548.          BEGIN°dONLNdS›<ËÆ*
  4549. J         StandardPutFile('Save PostScript file as','PostScript',ourReply);°dONLNdûÒ<¸©*I         IF ourReply.sfGood THEN {Did the user accept a file to save as?}°dONLNdË˚<ë*
  4550.             BEGIN°dONLNd˙<"*
  4551. .            IF ourReply.sfReplacing THEN BEGIN°dONLNd)<∏*
  4552. L               ourOSError := FSpDelete(ourReply.sfFile); { make sure this is°dONLNdv<$§*
  4553. H                                                          gone before we°dONLNdø#<.Ü*
  4554. B                                                          start! }°dONLNd-<8E*
  4555. 5               IF ourOSError <> noErr THEN AlertUser;°dONLNd87<Bå*
  4556.             END;°dONLNdIA<L—*
  4557. Q{OK, we're finally ready to pound the print record.  Put on your division by zero°dONLNdõK<Vd*
  4558. suit...}°dONLNd§U<`6*
  4559. 2            thePrRecHdl^^.prFlag1.fPSFile := TRUE;°dONLNd◊_<jã*
  4560. C            thePrRecHdl^^.psFileVRefNum := ourReply.sfFile.vRefNum;°dONLNd    i<t^*
  4561. :            tempPtr := NewPtr(64); {Size of reply.fName. }°dONLNd    Vs<~ü*
  4562. G            IF tempPtr = NIL THEN AlertUser; {SERIOUSLY low on memory }°dONLNd    û}<à«*
  4563. O{The LaserWriter driver will Dispos of this pointer before the end of the print°dONLNd    Óá<íZ*
  4564. loop.} ¡X¡
  4565. *(%PR 11 - Programmatic PostScript Files(÷5) of 6(ÏZM.PR.ProgrammaticPostScriptˇr◊#ˇ ˇˇˇˇ#◊ 
  4566. IR,Times
  4567. .+6-Macintosh Technical Notes /4/˘,
  4568. Courier
  4569.     °dONLNd(
  4570. *1            thePrRecHdl^^.pPSFileName := tempPtr;°dONLNd2'2v*
  4571. F            BlockMove(@ourReply.sfFile.name,thePrRecHdl^^.pPSFileName,°dONLNdy1<:*
  4572. :                      (LENGTH(ourReply.sfFile.name) + 1));°dONLNd¥;Fl*
  4573. D            thePrRecHdl^^.lastDirID := ourReply.sfFile.parID; {ID of°dONLNd˘EP—*
  4574. %               user-chosen directory}°dONLNdOZ«*
  4575. #            PrPSFileDialog := TRUE;°dONLNdCYd§*
  4576.          END {IF good THEN…}°dONLNd`cn©*
  4577.       END {if flag was clear}°dONLNd~mx;*
  4578.    END; ¡4¡˘
  4579. (÷66) of 6(÷Y%PR 11 - Programmatic PostScript Files+!M.PR.ProgrammaticPostScriptˇ◊#ˇ ˇˇˇˇ#◊†Ç 
  4580. /ZÅ#
  4581.     0Ià:µú9"{    ˇˇˇˇˇˇˇˇ#†ƒ°d
  4582. ONLNf˛†å°d1drw2…-·_ġˇˇˇˇˇè°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˙ó@†ò,Times
  4583. .R…R…+]BNew Technical Notes†ô°ddrw2:°„†ó°d1drw2eÙġˇˇˇˇˇP°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚ÄE¿†ò
  4584. ({ïDeveloper Support†ô°ddrw2:°„†ó°d`drw2-ÔˇˇˇˇˇˇKÔ- Z  ffZ°d1drw2 ¿˙ÈˇˇˇˇˇˇK°ñ x°ddrw2:°ddrw2:$°d4drw2:0°öˇÙĆò
  4585. 0(UÔ†ô°ddrw2:°„†ó°d1drw2ÔÊ˙ˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:    °öˇ˝Ä†ò
  4586.     +&    ®†ô°ddrw2:°„†ó°d1drw2Â-¯yˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚Ä%†ò
  4587. (Z\    Macintosh†ô°ddrw2:°„†ó†ç°ddrw2D†É
  4588. IR.°dONLNdˇˇ(õZPR 12 - SetLineWidth Revealed
  4589. °dONLNdˇˇ*Printing
  4590. °dONLNdˇˇ* Revised by:°dONLNdˇˇ(√„
  4591. March 1988°dONLNdˇˇ(œZ Written by:°dONLNdˇˇ)HScott "ZZ" Zimmerman°dONLNdˇˇ(œœ
  4592. November 1987°dONLNdˇˇ(ÁZQThis technical note describes the internal implementation, and correct method of °dONLNdˇˇ(ÁÍ
  4593. using, the,
  4594. Courier°dONLNdˇˇ(ÙZ SetLineWidth°dONLNdˇˇ)T Picture Comment. X°dONLNdˇˇ(ZThe °dONLNdˇˇ) SetLineWidth°dONLNdˇˇ)T picture comment provides °dONLNdˇˇ)úa way of accessing PostScript’s°dONLNdˇˇ(&Z#'setlinewidth' operator. Since the °dONLNdˇˇ)®8LaserWriter resolution is roughly four times that of the°dONLNdˇˇ(3ZMacintosh screen, fractional °dONLNdˇˇ)ã line widths can be printed. The °dONLNdˇˇ)° SetLineWidth°dONLNdˇˇ)T  PicComment°dONLNdˇˇ(?Zprovides a way for °dONLNdˇˇ)dGapplications to access these fractional line widths through PostScript,°dONLNdˇˇ(KZ-without having to use floating point numbers.°dONLNdˇˇ*4First of all, the LaserWriter has an internal state °dONLNdˇˇ)ı(that is stored in a number of PostScript°dONLNdˇˇ(oZvariables. For more °dONLNdˇˇ)l-information on PostScript variables, see the °dONLNdˇˇ)ÔPostScript Language°dONLNdˇˇ({ZReference Manual°dONLNdˇˇ)V#. Some operations performed on the °dONLNdˇˇ)≥%LaserWriter cause the values of these°dONLNdˇˇ(áZUvariables to change. One of these variables contains the width of the printer’s pen. °dONLNdˇˇ(á
  4595. The°dONLNdˇˇ(îZ SetLineWidth°dONLNdˇˇ)T> picture comment works by changing the value of this variable.°dONLNdˇˇ(≠ZBefore we look at what the °dONLNdˇˇ)Ç SetLineWidth°dONLNdˇˇ)T comment does, let’s °dONLNdˇˇ)elook at the argument passed°dONLNdˇˇ(πZto the comment. °dONLNdˇˇ)OKThe argument is represented as a QuickDraw Point, however it is interpreted°dONLNdˇˇ(ΔZ"by the LaserWriter as a fraction. °dONLNdˇˇ)ßThe LaserWriter interprets a °dONLNdˇˇ)ì
  4596. point(h,v)°dONLNdˇˇ)F
  4597.  to be a real°dONLNdˇˇ(”Znumber whose value is °dONLNdˇˇ)p(v °dONLNdˇˇ)/ h)°dONLNdˇˇ):. This means that a point whose value is h=2, v=1, will be°dONLNdˇˇ(flZ7converted to 0.5 before being used by the LaserWriter. °dONLNdˇˇ(fl`&If you wanted to pass a value of 0.25,°dONLNdˇˇ(ÎZRyou would pass a point whose value is h=4, v=1. For 1.25, pass a point, h=4, v= 5.°dONLNdˇˇ*TIn addition to the pen width variable, there is a variable that is used for scaling °dONLNdˇˇ(Õthe pen’s width.°dONLNdˇˇ(ZThis variable, named °dONLNdˇˇ)ipnm°dONLNdˇˇ)@ for PeN Multiplier, contains a real number which is applied to °dONLNdˇˇ(the°dONLNdˇˇ(Z pen width. The default value of °dONLNdˇˇ)ópnm°dONLNdˇˇ)3 is 1.0, which causes no scaling of the line width.°dONLNdˇˇ(6Z
  4598. Whenever the °dONLNdˇˇ)F SetLineWidth°dONLNdˇˇ)T( PicComment is sent to the LaserWriter, °dONLNdˇˇ)«the current value of°dONLNdˇˇ(CZpnm°dONLNdˇˇ)@ is replaced by the value passed to the PicComment. The current °dONLNdˇˇ(C†pen size is then scaled by°dONLNdˇˇ(PZthe new value of °dONLNdˇˇ)Upnm°dONLNdˇˇ)3. The following example will display four lines of °dONLNdˇˇ)˜different sizes. It is°dONLNdˇˇ(]Zmeant °dONLNdˇˇ)"4to illustrate the interaction between the QuickDraw °dONLNdˇˇ(]àPenSize°dONLNdˇˇ)1 procedure and the°dONLNdˇˇ(jZ SetLineWidth°dONLNdˇˇ)T  PicComment.
  4599.     °dONLNdˇˇ(ÅZTYPE°dONLNdˇˇ+$
  4600. widthHdl    = ^widthPtr;°dONLNdˇˇ*
  4601. widthPtr    = ^widthPt;°dONLNdˇˇ*
  4602. widthPt     = Point; ¡X¡
  4603. (÷ZPR 12 - SetLineWidth Revealed(÷1) of 4(ÏZM.PR.SetLineWidthˇ°¿Ù%%DSIDICT:_cv
  4604. currentdict /bu known {bu}if
  4605. userdict /_cv known not{userdict /_cv 30 dict put}if
  4606. _cv begin
  4607. /bdf{bind def}bind def
  4608. currentscreen/cs exch def/ca exch def/cf exch def
  4609. /setcmykcolor where{/setcmykcolor get /cvcmyk exch def}{/cvcmyk{1 sub 4 1 roll 3{3 index add neg dup 0 lt{pop 0}if 3 1 roll}repeat setrgbcolor pop}bdf }ifelse
  4610. /ss{//cf //ca //cs setscreen}bdf
  4611. /stg{ss setgray}bdf
  4612. /strgb{ss setrgbcolor}bdf
  4613. /stcmyk{ss cvcmyk}bdf
  4614. /min1{dup 0 eq{pop 1}if}bdf
  4615. end
  4616. currentdict /bn known {bn}if
  4617. †ø2◊#ˇ ˇˇˇˇ#◊ 
  4618. IR,Times
  4619. .+6-Macintosh Technical Notes /4/˘,
  4620. Courier
  4621.     °dONLNd('*VAR°dONLNd'2ï*
  4622.     theWidth:   widthHdl;°dONLNd;F1*BEGIN°dONLNd%O<Zˇ+$'(* Initialize the print manager as per °dONLNdLOˇZO)√Inside Macintosh°dONLNd\OOZÜ)P  II-155. *)
  4623. °dONLNdhfr≠(é6"At this point, it is assumed that °dONLNdäe≠qÛ)ï
  4624. PrPageOpen°dONLNdîfÛrˆ)F °dONLNdïfˆr⁄)/has been called, and the print manager is ready°dONLNd≈r~[(ö6to accept data.°dONLNd’äñ-*The °dONLNdŸä-ñ⁄)Zfirst thing we do is set the scaling factor to 1.0. This way, no scaling will be performed°dONLNd4ó£Y(ø6
  4625. when we call °dONLNdAñY¢ä)APenSize°dONLNdHóä£é)1.
  4626.     °dONLNdKØ<∫1(÷Z1theWidth := widthHdl(NewHandle(SizeOf(widthPt)));°dONLNd~π<ƒ*
  4627. ,(*Real programs do error checking here... *)°dONLNd¨√<Œ¥*
  4628. SetPt(theWidth^^, 1, 1);°dONLNdΔÕ<ÿh*
  4629. <PicComment(SetLineWidth, SIZEOF(widthPt), Handle(theWidth));
  4630. °dONLNd‰E( 6Here we °dONLNd ‰EZ)-call °dONLNd„ZÔã)PenSize°dONLNd‰ã”)1. Because the °dONLNd%„”ÔË)Hpnm°dONLNd(‰Ë⁄)1 has been set to 1.0, the pen size(1,1) times the°dONLNdZ¸ñ(6multiplier (1.0) yields 1,1.
  4631.     °dONLNdx<Ç+$PenSize(1, 1);°dONLNdà<å*
  4632. MoveTo(50, 100);°dONLNdö<'ë*
  4633. LineTo(500, 100);°dONLNd≠&<1å*
  4634. MoveTo(50, 125);°dONLNdø0<;·*
  4635. !DrawString('1 point thickness.');
  4636. °dONLNd·GSÇ(o6Now we will use the °dONLNdıFÇR÷)j SetLineWidth°dONLNdG÷Sé)T$ PicComment to change the pen size. °dONLNd%GéS⁄)∏Note that when°dONLNd4S_,({6;we change the scaling factor, the pen size changes as well.
  4637.     °dONLNdqk<v¥+$SetPt(theWidth^^, 1, 5);°dONLNdãu<Äh*
  4638. <PicComment(SetLineWidth, SIZEOF(widthPt), Handle(theWidth));°dONLNd…<äå*
  4639. MoveTo(50, 200);°dONLNd€â<îë*
  4640. LineTo(500, 200);°dONLNdÓì<ûå*
  4641. MoveTo(50, 225);°dONLNdù<®r*
  4642. >DrawString('5.0 times 1 point pen size = 5 point thickness.');
  4643. °dONLNd?¥¿[(‹6If any calls to °dONLNdO≥[øå)CPenSize°dONLNdV¥å¿K)1* are made at this point, the new pen size °dONLNdÄ¥K¿⁄)øwill be scaled by 5.0. This is°dONLNdü¡Õ](È6 because the °dONLNd´¿]ñ)E SetLineWidth°dONLNd∑¡±Õ’)T1 PicComment is still in effect. We will now send °dONLNdË¡’Õ⁄(ÈÛa°dONLNdÍÕŸl(ˆ6 SetLineWidth°dONLNdˆŒl⁄e)T5 PicComment to revert the scaling factor back to 1.0.
  4644.     °dONLNd,ÊÒ§(
  4645. 6    SetPt(theWidth^^, 5, 1);°dONLNdI˚X*
  4646. @    PicComment(SetLineWidth, SIZEOF(widthPt), Handle(theWidth));°dONLNdä˙|*
  4647.     MoveTo(50, 300);°dONLNdü|*
  4648.     LineTo(500,300);°dONLNdµ|*
  4649.     MoveTo(50, 325);°dONLNd #b*
  4650. B    DrawString('0.2 times 5 point pen size = 1 point thickness.');
  4651. °dONLNd
  4652. /;»*%Since the scaling is once again 1.0, °dONLNd2.»:˘)∞PenSize°dONLNd9/˘;∞)1) calls at this point will not be scaled. °dONLNdb/∞;⁄)∑Here we°dONLNdj;G»(c6)explicitly set the scaling factor to 1.0 °dONLNdì;»G⁄)∞9before changing the pen size. This makes it easier to see°dONLNdÕHTÒ(p61what scaling will be applied to the next call to °dONLNd˛GÒS")ŸPenSize°dONLNdH"T&)1.
  4653.     °dONLNd`k§(á6    SetPt(theWidth^^, 1, 1);°dONLNd$juX*
  4654. @    PicComment(SetLineWidth, SIZEOF(widthPt), Handle(theWidth));°dONLNdetr*
  4655.     PenSize(1, 1);°dONLNdx~â|*
  4656.     MoveTo(50, 400);°dONLNdçàì|*
  4657.     LineTo(500,400); ¡4¡˘
  4658. *'2) of 4(÷xPR 12 - SetLineWidth Revealed+-M.PR.SetLineWidthˇr◊#ˇ ˇˇˇˇ#◊ 
  4659. IR,Times
  4660. .+Z-Developer Support Center(-È  March 1988 /X/,
  4661. Courier
  4662.     °dONLNd<(†(DZ    MoveTo(50, 425);°dONLNd'<2Å*
  4663. A    DrawString('1.0 times 1 point pen size = 1 point thickness');°dONLNdW1<<m*
  4664. =    (* Dispose of the handle when you are through with it! *)°dONLNdï;<FÎ*
  4665. #    DisposHandle(Handle(theWidth));
  4666. °dONLNdπQ<]]*;When printed, the above example will produce the following:†Ç†é
  4667. àkx ò4P<P<àkƒ ÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕ—ˇÄÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕ˛¿å Ä⁄˝åÄ⁄¯xœèœåqô·¿fi˛Ã    ΔåÃ…±ôôì fi˛Ã    Δåá·ôô√Äfi˛Ã    Δåá¡ô¯·¿fi˛Ã    Δåá·ôÄp‡fi˛Ã    ΔåÃ…±ôâ2ffi¯xÃ√ÃÃqôò·Δfi˝¿“˝¿“ÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕò4<Px<Pxƒk ÕÕÕÕÕÕÕÕ—ˇÄ—ˇÄ—ˇÄ—ˇÄ—ˇÄÕÕÕÕÕÕÕÕÕÕÕÕÕÕ#˛¸Äc˝0˝˝    ?00Ò˛¿ ¿`˝8˝0¯0˝0Ò*˛$¿ ¿Û?··¿√Δ|x„?0·„><>1Δg√√áı+˛¯ ¿c˛3 ˛f 0ôôÅì3>˛3    33&ΔffLĈ*˛ ¿c˛3IJf 0ôôÅ√3˛333Üfgı*˛     ¿c33Ò¿˛f 0üôÄ„ ?˛333g„áı+˛     ¿c33‡˛f 0òÄs0˛3    33Üf√Ĉ+˛    åÿc33`˛f 0òôÅ301#˛3    33&Δf$…òˆ+˛%x«Ä331·¿√ΔfÄ„?·„3 31Δfc√áˆı˝¯Èı˝¯ÈÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕò4xP¥xP¥k< ÕÕÕÕÕÕÕÕ—ˇÄÕÕÕÕÕÕÕÕÕÕÕÕÕÕ#˛xÄc˝~0˝˝     00Ò˛ÿ`˝`˝0¯˝0Ò*˛$ÿÛ?··¿`√Δ|x„? ·„><>1Δg√√áı+˛ÿc˛3 |˛f 0ôôÅì3 ˛3    33&ΔffLĈ*˛ÃÄc˛3IJf 0ôôÅ√3 ˛333Üfgı*˛    Ãc33Ò¿˛f 0üôÄ„ ? ˛333g„áı+˛    Ãc33‡˛f 0òÄs0 ˛3    33Üf√Ĉ+˛    ÃÃc33`F˛f 0òôÅ301 ˛3    33&Δf$…òˆ+˛%xœ¿331·¿<√ΔfÄ„? ·„3 31Δfc√áˆı˝¯Èı˝¯ÈÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕò4¥P¥P<kx ÕÕÕÕ—ˇÄÕÕÕÕÕÕÕÕÕÕÕÕÕÕ#˛0Äc˝0˝˝     00Ò˛p ¿`˝8˝0¯˝0Ò*˛$0 ¿Û?··¿√Δ|x„? ·„><>1Δg√√áı+˛0 ¿c˛3 ˛f 0ôôÅì3 ˛3    33&ΔffLĈ*˛0 ¿c˛3IJf 0ôôÅ√3 ˛333Üfgı*˛    0 ¿c33Ò¿˛f 0üôÄ„ ? ˛333g„áı+˛    0 ¿c33‡˛f 0òÄs0 ˛3    33Üf√Ĉ+˛    0ÿc33`˛f 0òôÅ301 ˛3    33&Δf$…òˆ+˛%0«Ä331·¿√ΔfÄ„? ·„3 31Δfc√áˆı˝¯Èı˝¯ÈÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕ†è†É
  4668. IR°dONLNdıf<rp(éZ5To summarize, there are four things to remember when °dONLNd*fpr™(éé
  4669. using the °dONLNd4e™q˛): SetLineWidth°dONLNdAr<~|(öZ PicComment:°dONLNdMã<óF*1.°dONLNdPãNó°)The argument to °dONLNd`ã°ó¥)Sthe °dONLNddä¥ñ) SetLineWidth°dONLNdpãó˛)T1 PicComment is specified as a point, though it is°dONLNd¢óN£
  4670. (øl(actually interpreted by the LaserWriter °dONLNd ó
  4671. £˛)º1as a real number. The point value is specified as°dONLNd¸£NØc(Ãlh,v°dONLNdˇ§c∞3)., and the LaserWriter interprets the value as °dONLNd-£3ØV)–v / h°dONLNd2§V∞Z)#.°dONLNd4Ω<…F(ÂZ2.°dONLNd7ΩN…e)The °dONLNd;ºe»π) SetLineWidth°dONLNdGΩπ…©)T. PicComment affects both the height and width °dONLNduΩ©…˛)of the pen, even°dONLNdÜ…N’˝(Òl#though the name suggests otherwise.°dONLNd™‚<ÓF(
  4672. Z3.°dONLNd≠‚NÓû)When you send °dONLNdª‚ûÓ±)Pthe °dONLNdø·±Ì) SetLineWidth°dONLNdÀ‚Ó˛)T1 PicComment, the current pen size will be scaled.°dONLNd˝ÓN˙E(l1Any drawing that is done after the PicComment is °dONLNd.ÓE˙˛)˜%set, will be done with the scaled pen°dONLNdT˙Nd("lsize.°dONLNdZ<F(;Z4.°dONLNd]Nfl)When you call the QuickDraw °dONLNdyfl)ëPenSize°dONLNdÄZ)1 procedure, the °dONLNdêZ˛)J$pen size will be scaled after it has°dONLNdµN+ú(GlFbeen set. For example, if your scaling factor is 0.5, and you set the °dONLNd˚ú+˛(G∫pen size to 2,2, the°dONLNd+N7/(Sl/actual pen size will be 1,1. If you don’t want °dONLNd@+/7˛)·)the scaling to occur, make sure to send a°dONLNdk7NC¢(`l SetLineWidth°dONLNdw8¢D)T PicComment, with °dONLNdâ8D˛)e0the point argument set to 1,1.  The next call to°dONLNd∫DNP(mlPenSize°dONLNd¡EQ})17 will then be scaled by 1.0, which will have no effect. ¡X¡
  4673. (÷ZPR 12 - SetLineWidth Revealed(÷3) of 4(ÏZM.PR.SetLineWidthˇ,◊#ˇ ˇˇˇˇ#◊ 
  4674. IR,Times
  4675. .+6-Macintosh Technical Notes /4/˘
  4676. °dONLNd)Ç*Further Reference: H4H˘°dONLNd**6.+
  4677. •°dONLNd*<6Ã)LaserWriter Reference Manual°dONLNd26*B.(^H•°dONLNd46<Bˆ)$PostScript Language Reference Manual°dONLNdYB*N.(jH•°dONLNd[B<N))PostScript Language Tutorial and Cookbook ¡4¡˘
  4678. (÷64) of 4(÷xPR 12 - SetLineWidth Revealed+-M.PR.SetLineWidthˇæ◊#ˇ ˇˇˇˇ#◊°d WORDS †å°d WORDR…†Ç 
  4679. /ZÅ#
  4680.     0Ià:µú9"{    ˇˇˇˇˇˇˇˇ#†ƒ°d
  4681. ONLNf˛†å°d1drw2…-·_ġˇˇˇˇˇè°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˙ó@†ò,Times
  4682. .WIQkWIQk+]BNew Technical Notes†ô°ddrw2:°„†ó°d1drw2eÙġˇˇˇˇˇP°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚ÄE¿†ò
  4683. Ä({ïDeveloper Support†ô°ddrw2:°„†ó°d`drw2-ÔˇˇˇˇˇˇKÔ- Z  ffZ°d1drw2 ¿˙ÈˇˇˇˇˇˇK°ñ x°ddrw2:°ddrw2:$°d4drw2:0°öˇÙĆò
  4684. 0(UÔ†ô°ddrw2:°„†ó°d1drw2ÔÊ˙ˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:    °öˇ˝Ä†ò
  4685.     l+&    ®†ô°ddrw2:°„†ó°d1drw2Â-¯yˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚Ä%†ò
  4686. BÄ(Z\    Macintosh†ô°ddrw2:°„†ó†ç°ddrw2D†É°dWORD†ç
  4687. IR.°dONLNdo<Ç(úZPR 13 - Spooler Queries?
  4688. °dONLNdÅ<ês*Printing
  4689. °dONLNd#ú<®t* Revised by:°dONLNd0ú≈®˛(ƒ„
  4690. March 1988°dONLNd;®<¥q(–Z Written by:°dONLNdG®Ñ¥–)HGinger Jernigan°dONLNdW®œ¥˛(–Ì    July 1987 flXfl°dONLNdaÕ<Ÿ(ıZ%When the LaserShare spooler is on an °dONLNdÜÕŸ˛)ƒ2AppleTalk network, it acts like a LaserWriter-type°dONLNdπŸ<Âh(Z7device, which can be chosen and communicated with much °dONLNdŸh²(Ülike a real LaserWriter. Some°dONLNdÂ<Ò(
  4691. Z-applications, however, must communicate with °dONLNd;ÂÒ˛)‚1a LaserWriter directly, not a spooler. If this is°dONLNdmÒ<˝ (Ztrue for your application, you °dONLNdåÒ ˝˛)é@can check whether you are actually talking to a real LaserWriter°dONLNdÕ˝<    +(%Z2by sending to the LaserWriter the following query:,
  4692. Courier
  4693.     °dONLNd`!ƒ+$%!PS-Adobe-1.2 Query°dONLNd `+<*
  4694. ,%%Title: Query to Spooler/Non-Spooler status°dONLNdE*`5ƒ*
  4695. %%?BeginSpoolerQuery°dONLNd[4`?ó*
  4696. (0) = flush°dONLNdh>`Iƒ*
  4697. %%?EndSpoolerQuery 1°dONLNd~H`Sy*
  4698. %%EOF
  4699. °dONLNdÑ^<jê(ÜZG(The query has to be sent using the Printer Access Protocol (PAP). The °dONLNdÀ^êj˛(ÜÆobject code for PAP is°dONLNd‚j<vπ(íZPavailable from Licensing.) If the string returned begins with a ‘%%’ then it is °dONLNd2jπv˛(í◊a status string°dONLNdBv<Çñ(ûZIand you can ignore it and wait for another string. If the LaserWriter is °dONLNdãvñDz(û¥actually a LaserShare°dONLNd°Ç<éÑ(™ZJspooler, then the string that is returned will be ‘1’. If the LaserWriter °dONLNdÎÇÑé˛(™¢is a real LaserWriter then°dONLNdé<ö (∂Z the string returned will be ‘0’.°dONLNd'æ< ¶*0Further Reference: ÈXȰdONLNd:ÀN◊R+
  4700. •°dONLNd<À`◊)$PostScript Language Reference Manual°dONLNda◊N„R(ˇl•°dONLNdc◊`„T).Adobe Systems Document Structuring Conventions ¡X¡
  4701. (÷ZPR 13 - Spooler Queries?(÷1) of 1(ÏZM.PR.SpoolerQueriesˇ°¿Ù%%DSIDICT:_cv
  4702. currentdict /bu known {bu}if
  4703. userdict /_cv known not{userdict /_cv 30 dict put}if
  4704. _cv begin
  4705. /bdf{bind def}bind def
  4706. currentscreen/cs exch def/ca exch def/cf exch def
  4707. /setcmykcolor where{/setcmykcolor get /cvcmyk exch def}{/cvcmyk{1 sub 4 1 roll 3{3 index add neg dup 0 lt{pop 0}if 3 1 roll}repeat setrgbcolor pop}bdf }ifelse
  4708. /ss{//cf //ca //cs setscreen}bdf
  4709. /stg{ss setgray}bdf
  4710. /strgb{ss setrgbcolor}bdf
  4711. /stcmyk{ss cvcmyk}bdf
  4712. /min1{dup 0 eq{pop 1}if}bdf
  4713. end
  4714. currentdict /bn known {bn}if
  4715. †ø$◊#ˇ ˇˇˇˇ#◊†Ç 
  4716. /ZÅ#
  4717.     0Ià:µú9"{    ˇˇˇˇˇˇˇˇ#†ƒ°d
  4718. ONLNf˛†å°d1drw2…-·_ġˇˇˇˇˇè°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˙ó@†ò,Times
  4719. .R…R…+]BNew Technical Notes†ô°ddrw2:°„†ó°d1drw2eÙġˇˇˇˇˇP°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚ÄE¿†ò
  4720. ({ïDeveloper Support†ô°ddrw2:°„†ó°d`drw2-ÔˇˇˇˇˇˇKÔ- Z  ffZ°d1drw2 ¿˙ÈˇˇˇˇˇˇK°ñ x°ddrw2:°ddrw2:$°d4drw2:0°öˇÙĆò
  4721. 0(UÔ†ô°ddrw2:°„†ó°d1drw2ÔÊ˙ˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:    °öˇ˝Ä†ò
  4722.     +&    ®†ô°ddrw2:°„†ó°d1drw2Â-¯yˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚Ä%†ò
  4723. (Z\    Macintosh†ô°ddrw2:°„†ó†ç°ddrw2D†É
  4724. IR.°dONLNdn<ÅK(õZPR 14 - Dictionary Downloading
  4725. °dONLNdÄ<ès*Printing
  4726. °dONLNd)õ<ßq* Written by:°dONLNd5õÑßÃ)H Zz Zimmerman°dONLNdBõÀ߲(√È
  4727. April 1991°dONLNdM≥<øO(€Z7This technical note discusses a method for downloading °dONLNdÑ≥Oø˛(€m%PostScript dictionaries automatically°dONLNd™ø<À·(ÁZ"using the LaserWriter driver.  It °dONLNdÃø·À˛)•5will also provide the format and use of the PREC(103)°dONLNdÀ<◊0(ÛZ4resource.  It will also describe some problems with °dONLNd6À0◊˛)Ù(the now obsolete PREC(201) resource.  If°dONLNd_◊<„Í(ˇZ[you are using PostScript dictionaries, or either of these resources, you should definitely °dONLNd∫◊Í„˛(ˇread°dONLNdø„<Ôh( Z
  4728. this note. X
  4729. °dONLNd <#è*4 Introduction
  4730. °dONLNd◊/<;*ZAlthough many picture comments have been added to support the features of PostScript that °dONLNd1/;˛(Ware°dONLNd5;<GU(cZ9missing from Quickdraw, many developers have still taken °dONLNdn;UG˛(cs#to sending PostScript directly from°dONLNdíG<Sµ(oZRtheir applications.  As the use and complexity of this PostScript code increases, °dONLNd‰GµS˛(o”
  4731. more and more°dONLNdÚS<_Ò({Z$developers are finding it necessary °dONLNdSÒ_˛)µ4to define and use their own PostScript dictionaries.°dONLNdL_<kÛ(áZWPostScript dictionaries are basically collections of variables and procedures that can °dONLNd£_Ûk˛(ábe°dONLNd¶k<wu(ìZ predefined, °dONLNd≤kuw˛)9Pand accessed later.  They are used to prevent conflicts between the symbols used°dONLNdw<Éi(üZ?by applications and those used by system software (such as the °dONLNdBwiɲ(üáLaserWriter driver's LaserPrep°dONLNdaÉ<èJ(´Z8dictionary).  Unfortunately, because of the LaserWriter °dONLNdôÉJè˛(´h%drivers habit of using the PostScript°dONLNdøè<õ§(∑ZM'save' and 'restore' operators, there are problems with keeping a PostScript °dONLNd è§õ˛(∑¬dictionary defined.°dONLNd!õ<ß%(√Z.PostScript definitions made by code sent with °dONLNdOõ%߲)È,the print job (ie. sent between the calls to°dONLNd|ß<≥(œZ)PrOpenPage/PrClosePage) will be lost the °dONLNd•ß≥˛)‘2first time the LaserWriter driver calls 'restore'.°dONLNdŸ≥<øO(€Z9There are a couple of solutions to this problem, but one °dONLNd≥Oø˛(€m"that hasn't been documented before°dONLNd5ø<Àß(ÁZMinvolves the use of the PREC(103) resource.  If the LaserWriter driver finds °dONLNdÇøßÀ˛(Á≈a resource of type°dONLNdïÀ<◊w(ÛZ
  4732. PREC with °dONLNdüÀw◊⁄);Fan ID of 103, it will download the PostScript code to the LaserWriter °dONLNdÂÀ⁄◊˛(Û¯before°dONLNdÏ◊<„é(ˇZJperforming the initial 'save' operation.  This means that any definitions °dONLNd6◊鄲(ˇ¨made by the PostScript°dONLNdM„<ÔÆ( ZKcode stored in the PREC(103) resource will remain defined for the duration °dONLNdò„ÆÔ˛( Ãof the print job,°dONLNd™Ô<˚m(ZBindependent of the LaserWriter driver's calls to save and restore.
  4733. °dONLNdÌ<"n*'Caveats
  4734. °dONLNdı.<:Ê*LThe PREC(103) method is a great way to get a dictionary downloaded at print °dONLNdA.Ê:˛(Vtime.°dONLNdH:<F,(bZ3Unfortunately, this does not solve the problem for °dONLNd{:,F˛)-using dictionaries in export files like PICT.°dONLNd™F<R”(nZVIf you insert PostScript code into Quickdraw pictures, the system is not smart enough °dONLNd    F”R˛(nÒ    to record°dONLNd    
  4735. R<^æ(zZthe PREC(103) code into °dONLNd    "Ræ^˛)Ç?the picture.  Instead, you must record the dictionary using the°dONLNd    b^<jƒ(ÜZstandard PostScript picture °dONLNd    ~^ƒj˛)à;comments (defined in Technical Note #91, Optimizing for the°dONLNd    ∫j<vÍ(íZLaserWriter–PicComments).  You °dONLNd    ŸjÍv˛)Æ6should also use the appropriate PostScript structuring°dONLNd
  4736. v<Ǭ(ûZcomments as defined by the °dONLNd
  4737. +v¬ÇO)ÜAdobe Document Structuring °dONLNd
  4738. FvOÇã)ç Conventions°dONLNd
  4739. QvãDz)<.  If you use the Adobe°dONLNd
  4740. iÇ<é£(™Zcomments correctly, °dONLNd
  4741. }Ç£é˛)gEan application that is importing your picture will have the option of ¡X¡
  4742. (÷ZPR 14 - Dictionary Downloading(÷1) of 3(ÏZM.PR.DictionaryDownoadingˇ°¿Ù%%DSIDICT:_cv
  4743. currentdict /bu known {bu}if
  4744. userdict /_cv known not{userdict /_cv 30 dict put}if
  4745. _cv begin
  4746. /bdf{bind def}bind def
  4747. currentscreen/cs exch def/ca exch def/cf exch def
  4748. /setcmykcolor where{/setcmykcolor get /cvcmyk exch def}{/cvcmyk{1 sub 4 1 roll 3{3 index add neg dup 0 lt{pop 0}if 3 1 roll}repeat setrgbcolor pop}bdf }ifelse
  4749. /ss{//cf //ca //cs setscreen}bdf
  4750. /stg{ss setgray}bdf
  4751. /strgb{ss setrgbcolor}bdf
  4752. /stcmyk{ss cvcmyk}bdf
  4753. /min1{dup 0 eq{pop 1}if}bdf
  4754. end
  4755. currentdict /bn known {bn}if
  4756. †ø¯◊#ˇ ˇˇˇˇ#◊ 
  4757. IR,Times
  4758. .+6-Macintosh Technical Notes /4/˘
  4759. °dONLNd)/*;parsing for the procedure set comments, and extracting the °dONLNd;/)⁄(EM%dictionary definition to be placed in°dONLNda)5¬(Q6#a PREC(103) resource at print time.°dONLNdÖAMD*    The next °dONLNdéADM⁄),Pcaveat concerns the use of multiple PREC(103) resources.  At PrOpenDoc time, the°dONLNdflMYÁ(u6)LaserWriter driver makes one GetResource °dONLNdMÁY⁄)œ1call to load the resource of type PREC with an ID°dONLNd:Yeó(Å6Oof 103.  Because the call is a GetResource call (instead of Get1Resource), the °dONLNdâYóe⁄(ŵ PREC can be°dONLNdïeqr(ç6stored in any open °dONLNd®erq⁄)ZLresource file.  To avoid any conflicts, the resource should be stored in the°dONLNdıq}\(ô6resource fork °dONLNdq\}⁄)DOof your application, or in the document file that is referencing the PostScript°dONLNdS}â—(•6%dictionary.  Because the GetResource °dONLNdx}—â⁄)π4call is only made once, only the first PREC resource°dONLNd≠âïË(±6(found by GetResource will be used.  Any °dONLNd’âËï⁄)–.other PREC(103) resources will be ignored.  As°dONLNdï°z(Ω6long is this resource °dONLNdïz°⁄)bIis only used by applications, there is no problem since there can only be°dONLNdd°≠Ω(…6Zone application active at any particular time.  If the resource is used by other elements °dONLNdæ°Ω≠⁄(…€of the°dONLNd≈≠πQ(’6 system (ie. °dONLNd—≠Qπ⁄)9Ndesk accessories, drivers, INITs), you can easily run into the problem of your°dONLNd π≈ä(·6KPREC resource being ignored.  The best solution to this problem is to only °dONLNdkπä≈⁄(·®use the resource°dONLNd|≈—ò(Ì6from within an application.°dONLNdò›ÈF*
  4760. Since the °dONLNd¢›FÈ⁄).TPREC(103) resource is considered part of the print job, the definitions it makes are°dONLNd˜ÈıK(6
  4761. lost when °dONLNdÈKı⁄)3Nthe job ends (ie. when the LaserWriter receives EndOfFile from the Macintosh).°dONLNdQıO(6>Because of this, the code you place in the PREC(103) resource °dONLNdèıO⁄(mshould not attempt changing°dONLNd´
  4762. l()6Bany persistent parameters in the printer.  The means avoiding the °dONLNdÌl
  4763. ⁄()äPostScript 'exitserver'°dONLNd
  4764. (568operator.  You should also avoid calling other routines °dONLNd=
  4765. ⁄(5:+that reset the current state of the printer°dONLNdi%R(A6H(ie. initclip, initgraphics, etc.).  Use of these operators will have a °dONLNd±R%⁄(Apserious effect on Quickdraw°dONLNdÕ%1Û(M60operations that may be present in the print job.°dONLNd˛=Iû*NWhen the PREC(103) resource was originally introduced, it had a cousin called °dONLNdL=ûI⁄(eº
  4766. PREC(201).°dONLNdXIU∏(q6PREC(201) was similar to the °dONLNduI∏U⁄)†6PREC(103) resource in that it allowed PostScript to be°dONLNd¨Ua≠(}6Wdownloaded to the printer before the actual print job.  The difference between the two °dONLNdU≠a⁄(}À    resources°dONLNd
  4767. am£(â6Kwas that the PREC(201) resource downloaded the PostScript code at the same °dONLNdXa£m⁄(â¡ time that it°dONLNdemy∑(ï6Wdownloaded the LaserPrep dictionary, outside of the PostScript 'server loop'.  Because °dONLNdºm∑y⁄(ï’of this,°dONLNd≈yÖ(°62any definitions made by the code in the PREC(201) °dONLNd˜yÖ⁄)ˇ'resource would remain after the current°dONLNd    ÖëL(≠6?job.  Like the LaserPrep dictionary, the dictionary downloaded °dONLNd    ^ÖLë⁄(≠jin PREC(201) would remain°dONLNd    xëù%(π69until the LaserWriter was rebooted (ie. powered off then °dONLNd    ±ë%ù⁄(πC%on again).  Although this feature was°dONLNd    ◊ù©W(≈6Duseful in some situations, it did have its problems.  Not the least °dONLNd
  4768. ùW©⁄(≈uof which was the valuable°dONLNd
  4769. 5©µu(—6@printer memory consumed by the dictionary that was downloaded.  °dONLNd
  4770. u©uµ⁄(—ìSince the dictionary°dONLNd
  4771. 䵡ƒ(›6\remained after the job that required it, subsequent jobs had less memory available to them. °dONLNd
  4772. ʵƒ¡⁄(›‚ The°dONLNd
  4773. ΡÕG(È6    only way °dONLNd
  4774. Ù¡GÕ⁄)/Rto reclaim the memory was to reboot the printer, and this was not obvious to naive°dONLNd GÕŸP(ı6 users.  The °dONLNd SÕPŸ⁄)8Mother problem was introduced when background printing became available.  With°dONLNd °ŸÂÚ(6-background printing enabled, the LaserWriter °dONLNd ŒŸÚÂ⁄)⁄-driver could no longer count on the PREC(201)°dONLNd ¸ÂÒ¿(
  4775. 6!resource always being available. °dONLNd ¿Ò⁄)®4 Since you could no longer store the resource in the°dONLNd RÒ˝U(6 LaserWriter °dONLNd ^ÒU˝⁄)=Ldriver (because of the LaserWriter driver being MultiFinder compatible - see°dONLNd ´˝    o(%6Learning To Drive°dONLNd º˝o    r)W °dONLNd Ω˝r    ⁄)Mfor more information), it has to be stored in a separate resource file.  This°dONLNd
  4776.     «(16Umade it virtually impossible for the LaserWriter driver to find the resource when it °dONLNd
  4777. `    «⁄(1Âwas°dONLNd
  4778. d!G(=6
  4779. required. °dONLNd
  4780. nG!⁄)/K For this reason, the PREC(201) resource is only downloaded when background°dONLNd
  4781. ∫!-~(I6printing is turned off.°dONLNd
  4782. “9Eñ*Needless to say, we don't °dONLNd
  4783. Ï9ñE⁄)~Crecommend the use of features that only work in certain situations,°dONLNd0EQv(m6Fso the PREC(201) resource is now considered unsupported and obsolete. °dONLNdvEvQ⁄(mî If you are using the°dONLNdåQ]¢(y6MPREC(201) resource, you should be able to revise your application to use the °dONLNdŸQ¢]⁄(y¿    PREC(103)°dONLNd„]iC(Ö6    resource °dONLNdÏ]Ci⁄)+Rinstead, with only a small performance penalty.  On the bright side, the PREC(201)°dONLNd?iuE(ë6    resource °dONLNdHiEu⁄)-Nwill continue to be supported in the foreground through the 7.0 version of the°dONLNdóuÅÈ(ù6+LaserWriter driver, and most likely, until °dONLNd¬uÈÅ⁄)—0the new printing architecture becomes available,°dONLNdÛÅçΔ(©6&giving you plenty of time to revise... ¡4¡˘
  4784. *-2) of 3(÷sPR 14 - Dictionary Downloading+
  4785. M.PR.DictionaryDownoadingˇ™◊#ˇ ˇˇˇˇ#◊ 
  4786. IR,Times
  4787. .+Z-Developer Support Center(-
  4788. April 1991 /X/
  4789. °dONLNd5<D£(`ZImplementation
  4790. °dONLNdP<\**The PREC(103) resource can be implemented °dONLNd9P\˛)€/by simply creating the resource with ResEdit or°dONLNdi\<hÈ(ÑZ$Rez, and then storing it in an open °dONLNdç\Èh˛)≠9resource file at print time.  In the case of ResEdit, you°dONLNd«h<tÅ(êZBshould create a new resource of type PREC with an ID of 103.  You °dONLNd    hÅt˛(êüshould then open the new°dONLNd"t<ÄÉ(úZDresource using the resource template for string ('STR ') resources. °dONLNdftÉIJ(ú° You can then type your°dONLNd~Ä<å(®Z+PostScript code directly into the resource.°dONLNd™ò<§Ë*TIf you would rather keep your PREC definition as a Rez source file with the rest of °dONLNd˛ò˧˛(¿your°dONLNd§<∞d(ÃZ    project, °dONLNd §d∞˛)(Qyou can do this by simply defining the PREC resource type at the top of the file,°dONLNd^∞<º‡(ÿZVfollowed by an instance of the PREC resource.  Consider the following Rez source code:,
  4791. Courier
  4792.     °dONLNdµ»Ñ”e+H-    /* First the resource type definition: */°dONLNd„“Ñ›Ÿ*
  4793.     type 'PREC' {°dONLNdı‹ÑÁœ*
  4794.         string;°dONLNdÊÑÒ¢*
  4795.     };°dONLNd ˙Ñ[*+    /* Now the real resource definition: */°dONLNd8Ñ *
  4796.     resource 'PREC' (103) {°dONLNdTÑG*
  4797. '        "userdict /mydict 50 dict def";°dONLNd|Ñ#¢*
  4798.     };
  4799. °dONLNdÉ.<:·(VZVWe begin by defining the resource type as being a string.  We then define an instance °dONLNdŸ.·:˛(Vˇof the°dONLNd‡:<F(bZresource with °dONLNdÓ:F˛)COan ID of 103.  Finally, we define the contents of the resource.  The PostScript°dONLNd>F<R“(nZcode above basically defines a °dONLNd]F“R˛)ñ<dictionary named mydict within the userdict dictionary.  The°dONLNdöR<^ü(zZmydict dictionary is °dONLNdØRü^˛)cCdefined as having a maximum of 50 elements.  Consult the PostScript°dONLNdÛ^<j¯(ÜZ[Language Reference Manual for more information concerning legal operations on dictionaries.
  4800. °dONLNdOÇ<ëÖ*'
  4801. Conclusion
  4802. °dONLNdZù<©±*MThe PREC(103) is a simple, efficient way to download a PostScript dictionary °dONLNdßù±©˛(≈œat print time.  It°dONLNd∫©<µ~(—ZEdoes not solve the problem of exporting PostScript that references a °dONLNdˇ©~µ˛(—údictionary into file formats°dONLNdµ<¡ô(›Zsuch as PICT, but °dONLNd.µô¡˛)]Jit can help.  Applications can be revised to extract PostScript dictionary°dONLNdy¡<ÕE(ÈZ6definitions from files such as PICT and download them °dONLNdØ¡EÕ˛(Èc&at print time using the PREC(103).  It°dONLNd÷Õ<Ÿê(ıZIshould be noted however that this is not automatic, the application must °dONLNdÕêŸ˛(ıÆparse the picture to get°dONLNd8Ÿ<Âí(Zthis functionality. °dONLNdLŸí²)VF Finally, the PREC(201) resource can only be supported when background°dONLNdìÂ<Ò¬(
  4803. ZUprinting is disabled, so it is now considered obsolete, and use of it is unsupported.°dONLNdÈ<!¶*0Further Reference: @X@°dONLNd¸"N.R+
  4804. •°dONLNd˛"`.Å)8PostScript Language Reference Manual, Adobe Systems Inc.°dONLNd7.N:R(Vl•°dONLNd9.`:ê):Adobe Document Structuring Conventions, Adobe Systems Inc.°dONLNdt:NFR(bl•°dONLNdv:`FF),LaserWriter Reference Manual, Addison-Wesley°dONLNd£R<^Ä(zZCPostScript is a registered trademark of Adobe Systems Incorporated. ¡X¡
  4805. *\PR 14 - Dictionary Downloading(÷3) of 3(ÏZM.PR.DictionaryDownoadingˇP◊#ˇ ˇˇˇˇ#◊†Ç 
  4806. /ZÅ#
  4807.     0Ià:µú9"{    ˇˇˇˇˇˇˇˇ#†ƒ°d
  4808. ONLNf˛†å°d1drw2…-·_ġˇˇˇˇˇè°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˙ó@†ò,Times
  4809. .R…R…+]BNew Technical Notes†ô°ddrw2:°„†ó°d1drw2eÙġˇˇˇˇˇP°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚ÄE¿†ò
  4810. ({ïDeveloper Support†ô°ddrw2:°„†ó°d`drw2-ÔˇˇˇˇˇˇKÔ- Z  ffZ°d1drw2 ¿˙ÈˇˇˇˇˇˇK°ñ x°ddrw2:°ddrw2:$°d4drw2:0°öˇÙĆò
  4811. 0(UÔ†ô°ddrw2:°„†ó°d1drw2ÔÊ˙ˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:    °öˇ˝Ä†ò
  4812.     +&    ®†ô°ddrw2:°„†ó°d1drw2Â-¯yˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚Ä%†ò
  4813. (Z\    Macintosh†ô°ddrw2:°„†ó†ç°ddrw2D†É
  4814. IR.°dONLNdn<Ř(õZPR 15 - Feeder Fodder
  4815. °dONLNdÄ<ès*Printing
  4816. °dONLNd õ<ßq* Written by:°dONLNd,õÑßÃ)H Zz Zimmerman°dONLNd9õÀ߲(√È
  4817. April 1991°dONLNdD≥<ø(€Z-This Technical Note discusses the new Feeder °dONLNdq≥ø˛)›0button available in the 6.1, and 7.0 versions of°dONLNd¢ø<À§(ÁZHthe LaserWriter driver.  This Feeder button mechanism allows developers °dONLNdÍø§À˛(Á¬to insert code into°dONLNd˛À<◊Á(ÛZSthe LaserWriter driver to support a sheet feeder connected to a LaserWriter.  This °dONLNdQÀÁ◊˛(ÛNote°dONLNdV◊<„‘(ˇZWprovides a description of the button, as well as information required to implement one. X
  4818. °dONLNdÆ<è*4 Introduction
  4819. °dONLNdª#</Ê*UThe LaserWriter driver now implements a standard method for handling sheet feeders.  °dONLNd#Ê/˛(KMost°dONLNd/<;–(WZPLaserWriter sheet feeders need a way to present a user with a dialog as well as °dONLNde/–;˛(WÓa way to°dONLNdn<<H∫(dZdownload the PostScript
  4820.     °dONLNdÖ:∫E¡(aÿ®
  4821. °dONLNdÜ<¡H∞++ code necessary to control the feeder.  In °dONLNd±<∞H˛)Ôthe past, most°dONLNd¿H<T≠(pZmanufacturers resorted °dONLNd◊H≠T˛)qCto modifying the LaserWriter driver’s code resources; however, this°dONLNdT<`Û(|Z&functionality is now possible without °dONLNdATÛ`˛)∑5the need to patch existing resources in the driver—by°dONLNdw`<l¡(àZadding three new resources.°dONLNdìx<Ñ]*When °dONLNdòx]Ñ˛)!Uthe LaserWriter driver notices these three special resources in its resource fork, it°dONLNdÓÑ<ê™(¨ZMdisplays a Feeder button in the lower right corner of the Print dialog box.  °dONLNd;Ñ™ê˛(¨»It is important to°dONLNdNê<ú˘(∏Z+note that this feature is not provided for °dONLNdyê˘ú˛)Ω7general application use, but rather only for developers°dONLNd±ú<®I(ƒZof °dONLNd¥úI®˛)
  4822. Ysheet feeders and other LaserWriter add-on devices.  The button is always labeled Feeder,°dONLNd®<¥Ì(–ZYand there can be only one set of Feeder resources in the LaserWriter driver.  Because of °dONLNdg®Ì¥˛(– this°dONLNdl¥<¿Ì(‹Z'restriction, you should not attempt to °dONLNdì¥Ì¿˛)±9use this feature to implement anything other than a sheet°dONLNdÕ¿<Ã](ËZfeeder.°dONLNd’ÿ<‰*\The first special resource contains code to implement the user interface of the feeder, and °dONLNd1ÿ‰˛(the°dONLNd5‰<W( Zother °dONLNd;‰W˛)Xtwo contain the PostScript code required to drive the feeder.  When an application calls°dONLNdî<¸¬(ZSthe LaserWriter driver to display the Print dialog box, the driver looks for three °dONLNdÁ¬¸˛(‡ resources of°dONLNdÙ˝<    S(%Ztype ,
  4823. Courier°dONLNd˘¸S})'feed'°dONLNdˇ˝}    à)*: and displays the Feeder button in the lower right corner °dONLNd9˝à    ˛(%¶of the dialog box if they°dONLNdS
  4824. <ç(2Zare found.  If no °dONLNde    ç∑)Q'feed'°dONLNdk
  4825. ∑⁄)*@ resources are available, it does not display the Feeder button.°dONLNd¨"<.(JZ/When a user selects Print, the driver displays °dONLNd€".˛)‡-the standard Print dialog box with the Feeder°dONLNd    .<:a(VZbutton. °dONLNd.a:˛)%X If a user clicks on the Feeder button, the driver displays a dialog box in front of the°dONLNdj:<Fj(bZAPrint dialog box, which allows the user to configure the feeder, °dONLNd´:jF˛(bà then returns to the Print dialog°dONLNdÃF<R"(nZ1box once the user confirms or cancels the feeder °dONLNd˝F"R˛)Ê-configuration.  This feeder dialog box should°dONLNd    +R<^N(zZnot°dONLNd    .RN^ )+ contain an option to print, as this could °dONLNd    YR ^˛)æ2override choices made in the standard Print dialog°dONLNd    å^<jR(ÜZbox. ¿X¿
  4826. *PPR 15 - Feeder Fodder(÷1) of 6(ÏZM.PR.FeederFodderˇ°¿Ù%%DSIDICT:_cv
  4827. currentdict /bu known {bu}if
  4828. userdict /_cv known not{userdict /_cv 30 dict put}if
  4829. _cv begin
  4830. /bdf{bind def}bind def
  4831. currentscreen/cs exch def/ca exch def/cf exch def
  4832. /setcmykcolor where{/setcmykcolor get /cvcmyk exch def}{/cvcmyk{1 sub 4 1 roll 3{3 index add neg dup 0 lt{pop 0}if 3 1 roll}repeat setrgbcolor pop}bdf }ifelse
  4833. /ss{//cf //ca //cs setscreen}bdf
  4834. /stg{ss setgray}bdf
  4835. /strgb{ss setrgbcolor}bdf
  4836. /stcmyk{ss cvcmyk}bdf
  4837. /min1{dup 0 eq{pop 1}if}bdf
  4838. end
  4839. currentdict /bn known {bn}if
  4840. †øÏ◊#ˇ ˇˇˇˇ#◊ 
  4841. IR,Times
  4842. .+6-Macintosh Technical Notes /4/˘
  4843. °dONLNd,*Implementation
  4844. °dONLNd9EÂ*)To handle interaction with the user, you °dONLNd89ÂEá)Õ must install a resource of type ,
  4845. Courier°dONLNdX8áD±)¢'feed'°dONLNd^9±Eª)* (°dONLNd`8ªD⁄)
  4846. ID =°dONLNdeEQ;(n6-8192°dONLNdjF;RÎ)#') into the LaserWriter driver with the °dONLNdëFÎR⁄)∞1code required to manage the dialog box.  Like all°dONLNd√R^j(z6BPrinting Manager code resources, this resource begins with a jump °dONLNdRj^⁄(zàtable, followed by the°dONLNd^jS(Ü6
  4847. actual code. °dONLNd)^Sj⁄);P The code is implemented as a procedure that is passed a single parameter.  This°dONLNdzjvû(í6Vparameter is a rectangle defining the page size selected by the user.  This page size °dONLNd–jûv⁄(íº
  4848. is equivalent°dONLNdfiwÉ5(ü6to the °dONLNdÂv5Ç_)rPaper°dONLNdÎw_ɧ)*I rectangle in the print record, meaning it defines the actual page size, °dONLNd4w§É⁄(ü¬ not just the°dONLNdAÉèø(´6\printable area.  The rectangle is expressed in 72 dpi coordinates and has a negative origin.
  4849. °dONLNdûß∂ú*'Go Ahead and Jump
  4850. °dONLNd∞√œŒ*#The jump table consists of a 68000 °dONLNd”¬ŒŒ„)∂JMP°dONLNd÷√„œú)& instruction that jumps to the proper °dONLNd¸√úœ⁄)π
  4851. offset in the°dONLNd
  4852. œ€k(˜6resource.  In this °dONLNdœk€⁄)SMcase, there is only one routine, so the code starts immediately following the°dONLNdk€Ág(6jump table.  To °dONLNd{€gÁ⁄)OJmake this step automatic, the jump table is created using a small assembly°dONLNdΔÁÛg(6language header:
  4853.     °dONLNdŸˇ`
  4854. ~+HIMPORT°dONLNd‡ˇÑ
  4855. ¢)$Feeder°dONLNdˡÃ
  4856. g)H; Feeder is NOT defined here...°dONLNd        <U(0ZStart°dONLNd    `t)$MAIN°dONLNd    Ñ∞)$<EXPORT        ; This is the main entry point for the linker.°dONLNdS`o(:~JMP°dONLNdWÑó)$7Feeder        ; The one jump table entry in this table.°dONLNdë`(o(D~END
  4857. °dONLNdï4@≤(\6This example first imports the °dONLNd¥3≤?‹)öFeeder°dONLNd∫4‹@`)* procedure, which can be °dONLNd”4`@⁄)Ñdefined externally in the°dONLNdÌAM∏(i6"language of your choice.  Next is °dONLNd@∏L€)†Start°dONLNdA€M‚)#, °dONLNdA‚M⁄)3the main entry point to the jump table.  By passing°dONLNdJMYÿ(u6)this label to the link command, the jump °dONLNdsMÿY⁄)¿7table is located at the beginning of the resource.  The°dONLNd´ZfN(Ç6
  4858. next line is °dONLNd∏ZNf¸)6%the actual jump table entry, and the °dONLNd›Y¸e)ÆEND°dONLNd‡Zf⁄)) is required to end the assembly-language°dONLNd
  4859. frL(é6?header.  That’s all there is to it.  The only thing one should °dONLNdIfLr⁄(éjhave to change in this code°dONLNder~(ö64fragment would be the name of the routine to import.
  4860. °dONLNdöñ•î*'The Real MacCode
  4861. °dONLNd´±Ωù*Now that the jump table is °dONLNdΔ±ùΩ⁄)Ö:complete, it needs some place to jump.  Although MPW C and°dONLNdΩ…5(Â68Pascal examples are provided in this Note, the code can °dONLNd9Ω5…⁄(ÂSbe written in any language.  As°dONLNdY…’°(Ò6Rmentioned before, the code is implemented as a procedure that takes one parameter.°dONLNd¨·Ì^* C Definition°dONLNdπ˘y*In C, this looks like:
  4862.     °dONLNd–Ü*    #include <Types.h>°dONLNdÁ&ö*
  4863.     #include <Quickdraw.h>°dONLNd%0ê*
  4864.     void FEEDER(Rect *r)°dONLNd/:1*
  4865.     {°dONLNd!9D˛*
  4866. .        <Code to present and handle dialog...>°dONLNdPCN1*
  4867.     }
  4868. °dONLNdVZfœ*(Since the assembler converts all labels °dONLNd~Zœfï)∑(to uppercase, the name of the procedure °dONLNd¶Yïeø)ΔFEEDER°dONLNd¨Zøf⁄)* must°dONLNd≤fr(é6:be capitalized to match the case of the label in the jump °dONLNdÏfr⁄(é:%table.  If you are using MPW, you can°dONLNd    sw(õ6use the assembler's °dONLNd    &rw~ì)_CASE°dONLNd    *sìô): directive to prevent the assembler from capitalizing the °dONLNd    dsô⁄(õ∑labels.  Since°dONLNd    sãà(ß6the rectangle is passed °dONLNd    ãàã⁄)pGusing the C calling convention (i.e., the caller strips the parameter), ¿4¿˘
  4869. (÷62) of 6(÷üPR 15 - Feeder Fodder+
  4870. M.PR.FeederFodderˇê◊#ˇ ˇˇˇˇ#◊ 
  4871. IR,Times
  4872. .+Z-Developer Support Center(-
  4873. April 1991 /X/
  4874. °dONLNd<*(FZ*there is no need to declare the procedure °dONLNd**,)»as type ,
  4875. Courier°dONLNd2,)V)(Pascal°dONLNd8V*˛)* .  However, this convention does°dONLNdY*<6O(RZ=make things a little more interesting for the Pascal version:°dONLNdóB<Nù*Pascal Definition°dONLNd©[<gp* If you are °dONLNd¥[pgb)4-using MPW, you can use the Pascal compiler's °dONLNd·Zbfi)ÚC°dONLNd‚[ig˛) directive to define the Feeder°dONLNdg<sŒ(èZWprocedure as using the C calling convention.  This makes the definition look like this:
  4876.     °dONLNdZ<ä™*    UNIT FeederSample;°dONLNdqâ<îë*
  4877.         INTERFACE°dONLNdÑì<ûÊ*
  4878. "            USES Types, Quickdraw;°dONLNdßß<≤ı*%        PROCEDURE Feeder(r: Rect); C;°dONLNdÕª<Δ™*        IMPLEMENTATION°dONLNd‰œ<⁄Ê*"        PROCEDURE Feeder(r: Rect);°dONLNdŸ<‰}*
  4879.  
  4880.         BEGIN°dONLNd„<Ó6*
  4881. 2            <Code to present and handle dialog...>°dONLNdPÌ<¯x*
  4882.         END;°dONLNd]˜<d*
  4883.     END.
  4884. °dONLNdf
  4885. <÷*"So this is straight forward.  The °dONLNdà
  4886. ÷˛)ö<procedure Feeder is defined as having one parameter (r), and°dONLNd≈<%U(AZ?the C directive is used so that the stack is handled correctly.°dONLNd1<=∞*MIf you are using some other development environment that doesn't support the °dONLNdS1∞=˛(YŒC directive, you°dONLNdd=<Iq(eZDhave to do a little more work, making the definition look like this:
  4887.     °dONLNd©U<`™*    UNIT FeederSample;°dONLNd¿_<jë*
  4888.         INTERFACE°dONLNd”i<tÊ*
  4889. "            USES Types, Quickdraw;°dONLNdˆ}<àπ*        PROCEDURE Feeder;°dONLNdë<ú™*        IMPLEMENTATION°dONLNd'•<∞*(        FUNCTION StealRectalParam: Rect;°dONLNdPØ<∫ö*
  4890. F            INLINE    $2EAE, 0008;        { MOVE.L        8(A6),(A7) }°dONLNdó√<Œπ*        PROCEDURE Feeder;°dONLNd±Õ<ÿs*
  4891.         VAR°dONLNdΩ◊<‚Ø*
  4892.             r:    Rect;°dONLNd’·<Ï}*
  4893.  
  4894.         BEGIN°dONLNd„Î<ˆÊ*
  4895. "            r := StealRectalParam;°dONLNdˇ<
  4896. 6*2            <Code to present and handle dialog...>°dONLNdB    <x*
  4897.         END;°dONLNdO<d*
  4898.     END.
  4899. °dONLNdX)<5Ä*First of all, a °dONLNdh)Ä5˛)DOunit is defined, and the proper interfaces are included.  The definition of the°dONLNd∏5<Af(^ZFeeder°dONLNdæ6fB≠)* procedure in °dONLNdÃ6≠B¡)Gthe °dONLNd–5¡A)    INTERFACE°dONLNdŸ6B˛)?3 section is required to make the label available to
  4900. °dONLNd
  4901. C<OÊ(kZexternal modules.  In the °dONLNd'BÊNH)™IMPLEMENTATION°dONLNd5CHOá)b
  4902.  section,  °dONLNd?CáO˛)?one starts with the°dONLNdSO<[¨(xZStealRectalParam°dONLNdcP¨\ƒ)p8 function, which is used to get the rectangle passed by °dONLNdõPƒ\˛(x‚ the Printing°dONLNd®\<h˘(ÑZ%Manager without actually removing it °dONLNdÕ\˘h˛)Ω3from the stack.  If you declared the rectangle as a°dONLNdi<uç(ëZparameter to the °dONLNdhçt∑)QFeeder°dONLNdi∑uÚ)*  procedure, °dONLNd$hÚt);Feeder°dONLNd*iuœ)*# would remove the parameter before °dONLNdMiœu˛)≥
  4903. returning,°dONLNdXu<ÅZ(ùZ>then when the caller tried to remove the parameter again, the °dONLNdñuZŞ(ùx stack would be invalid and would°dONLNd∑Å<ç~(©Zcause a crash. ¿X¿
  4904. *-PR 15 - Feeder Fodder(÷3) of 6(ÏZM.PR.FeederFodderˇå◊#ˇ ˇˇˇˇ#◊ 
  4905. IR,Times
  4906. .+6-Macintosh Technical Notes /4/˘
  4907. °dONLNd*6√*%"To solve this problem, define the ,
  4908. Courier°dONLNd")√5Ì)´Feeder°dONLNd(*Ì6ç)* procedure with no parameters. °dONLNdG*ç6⁄)† This way, the°dONLNdV6BB(_6Feeder°dONLNd\7BCfi)*  procedure leaves the parameter °dONLNd|7fiC⁄)ú5right where the caller left it.  To get the parameter°dONLNd≤DPÊ(l6,without removing it from the stack, use the °dONLNdfiCÊOV)ŒStealRectalParam°dONLNdÓDVPY)p °dONLNdÔDYP⁄)function, which moves the°dONLNd    Q]fl(y6+parameter from its normal location (off of °dONLNd4Pfl\Ì)«A6°dONLNd6QÌ]) ) into the °dONLNdAQ]⁄)-)location pointed to by the stack pointer.°dONLNdl^j6(Ü6Since °dONLNdr]6i¶)StealRectalParam°dONLNdÇ^¶j´)p9 is a function, the stack pointer is already pointing to °dONLNdª^´j⁄(Ü…
  4909. the return°dONLNdΔkwi(ì6
  4910. value.  When °dONLNd”jivŸ)QStealRectalParam°dONLNd„kŸw$)p returns, the °dONLNdÒj$vN)KFeeder°dONLNd˜kNw∞)* routine gets the °dONLNd    k∞w⁄)b    rectangle°dONLNdwÉ(ü64parameter, without having removed it from the stack.°dONLNdHèõ`* Tickled Link°dONLNdUß≥*2Now you have the jump table and the code, but you °dONLNdáß≥⁄)˜,still need to link them together.  This step°dONLNd¥≥øg(€6is pretty simple, °dONLNdΔ≥gø⁄)OObut remember to specify the starting location of the jump table.  It looks like°dONLNdøÀZ(Á6the following:
  4911.     °dONLNd%◊‚W*@    Link -w -t feed -c ZzZz -rt feed=-8192 -m START -sg Feeder ∂°dONLNdf·ÏC*
  4912. <        Feeder.a.o ∂              # This file MUST be first.°dONLNd£Îˆ{*
  4913.         Feeder.p.o ∂°dONLNd∏ı∑*
  4914.          "{Libraries}"Runtime.o ∂°dONLNdŸˇ
  4915. ¡*
  4916. "        "{Libraries}"Interface.o ∂°dONLNd¸    º*
  4917. !        "{PLibraries}"SANELib.o ∂°dONLNd∑*
  4918.          "{PLibraries}"PasLib.o ∂°dONLNd?(m*
  4919.         -o Feeder
  4920. °dONLNdQ4@Ÿ*.First tell the linker to link the code into a °dONLNd3Ÿ?)¡'feed'°dONLNdÖ4@ô)*  resource with an ID of -8192.  °dONLNd•4ô@⁄)ñ
  4921. Next, specify°dONLNd≥AM(i60that the resource begins with the code at label °dONLNd„@L)ÿSTART°dONLNdËAM™)#!.  This label was defined by the °dONLNd    A™M÷)óassembly°dONLNdA÷M⁄),-°dONLNdMYE(u6    language °dONLNdMEY⁄)-Yused to generate the jump table.  Finally, tell the linker to link all of the code into a°dONLNduZfâ(Ç6single segment named °dONLNdäYâe≥)qFeeder°dONLNdêZ≥fº)*. °dONLNdíZºf⁄)    : Obviously, the list of libraries and object files changes°dONLNdÕfr•(é6depending upon the language °dONLNdÈf•r⁄)ç>used, but the directives to the Link command should remain the°dONLNd(r~4(ö6same.°dONLNd.äñK*Well Fed°dONLNd7£Øq*So that should be °dONLNdI£qØ)Y!enough to get some code into the °dONLNdj¢ÆG)¨'feed'°dONLNdp£GØ⁄)* resource.  Now you need to°dONLNdåØªR(◊6Cactually control the feeder during the print job.  To do this, you °dONLNdœØRª⁄(◊pmust use PostScript.  Your°dONLNdͺ»ü(‰6driver should also provide a °dONLNdªü«…)á'feed'°dONLNd
  4922. º…»´)*0 resource of -8191 containing PostScript code.  °dONLNd=º´»⁄)‚    This code°dONLNdG»‘¡(6Wis downloaded by the LaserWriter driver prior to downloading the rest of the job.  For °dONLNdû»¡‘⁄(flthose°dONLNd§’·h(˝6familiar with the °dONLNd∂‘h‡í)P'PREC'°dONLNdº’í·;)*% 103 resource, the PostScript in the °dONLNd·‘;‡e)©'feed'°dONLNdÁ’e·h)* °dONLNdË’h·⁄)resource is downloaded°dONLNdˇ‚Ó<(
  4923. 6before°dONLNd‚<ÓT)$ the °dONLNd
  4924. ·TÌ~)'PREC'°dONLNd‚~Óá)*3 103 code.  Additional PostScript to be downloaded °dONLNdC‚áÓ⁄(
  4925. •can be stored in°dONLNdTÓ˙B(6'feed'°dONLNdZÔB˚Í)*$ -8190.  The PostScript code in the °dONLNd~ÓÍ˙)®'feed'°dONLNdÑÔ˚e)* resource should °dONLNdïÔe˚⁄)Qredefine (i.e., patch) the°dONLNd∞˚É(#6PostScript operators °dONLNd≈˚É⁄)k@required to handle switching feeders.  A likely candidate is the°dONLNd    P(06showpage°dONLNd    P )8. operator called at the end of each page.  As °dONLNd    < ⁄)–'always, calling or redefining operators°dONLNd    d 3(<6<defined by the LaserPrep (md) dictionary is not supported.  °dONLNd    †3 ⁄(<Q#If your device is connected via the°dONLNd    ƒ ,Ø(H6NLaserWriter’s serial port, you can license code from Adobe Systems, Inc. that °dONLNd
  4926.  Ø,⁄(HÕmakes it°dONLNd
  4927. ,8p(T6Kpossible to access the serial port while the LaserWriter is connected over °dONLNd
  4928. f,p8⁄(TéAppleTalk.  For more°dONLNd
  4929. {8Dß(`6information, contact Adobe at:°dONLNd
  4930. ùPÑ\Ë+lAdobe Systems, Inc.°dONLNd
  4931. ¥\ÑhÓ* 1585 Charleston Road°dONLNd
  4932. ÃhÑt* Mountain View, CA  94043°dONLNd
  4933. ËtÑÄœ* (415) 961-4400 ¿4¿˘
  4934. (÷64) of 6(÷üPR 15 - Feeder Fodder+
  4935. M.PR.FeederFodderˇ◊#ˇ ˇˇˇˇ#◊ 
  4936. IR,Times
  4937. .+Z-Developer Support Center(-
  4938. April 1991 /X/
  4939. °dONLNd<)_(EZOnce a °dONLNd_)˛)#Uuser has confirmed the configuration from the dialog box, you can edit the PostScript°dONLNd])<5˘(QZ*code in the -8191 resource to reflect the °dONLNdá)˘5˛)Ω3choices made.  However, when MultiFinder is active,°dONLNdª5<As(]ZByou cannot add or change the size of resources in the LaserWriter °dONLNd˝5sA˛(]ëdriver.  For this reason, you°dONLNdB<NÑ(jZshould pad the ,
  4940. Courier°dONLNd*AÑMµ)H'feed' °dONLNd1BµN˛)1@-8191 resource to the maximum size.  This padding can be done by°dONLNdrN<ZÄ(vZEadding spaces at the end.  If you later need to resize the resource, °dONLNd∑NÄZ˛(vûyou can simply overwrite°dONLNd–Z<fø(ÇZsome of the spaces.  For °dONLNdÈZøf˛)É>more information on printer drivers under MultiFinder, see the°dONLNd(f<rì(éZLearning to Drive°dONLNd9fìr)W document, which is part °dONLNdRfr˛)Ç.of “Developer Essentials,” and is available on°dONLNdÅr<~`(öZ;AppleLink, the Apple FTP site, and the Developer CD Series.°dONLNdΩã<ó4*3You probably need to provide other resources along °dONLNdã4ó_)¯    with the °dONLNd˘ä_ñâ)+'feed'°dONLNdˇãâó˛)* resources; for example,°dONLNdò<§j(¿Z    you need °dONLNd!ój£î).'DITL'°dONLNd'òî§´)* and °dONLNd,ó´£’)'DLOG'°dONLNd2ò’§π)*2 resources for the dialog box.  This is okay, but °dONLNddòπ§˛)‰
  4941. you should be°dONLNdr§<∞Ï(ÃZ&sure to pick unique resource types to °dONLNdò§Ï∞˛)∞9avoid confusing the LaserWriter driver.  In the case of a°dONLNd“∞<ºù(ÿZJFeeder button, you are a guest in someone else’s house.  It would be wise °dONLNd∞ùº˛(ÿªto avoid rearranging°dONLNd1º<»z(‰Zthe furniture.°dONLNd@’<·*/When the LaserWriter driver actually opens the °dONLNdo’·‘)·(connection to the printer, it looks for °dONLNd󑑇˛)∑'feed'°dONLNdû·<Ì÷(    ZTresources -8191 and -8190.  If they exist, they are downloaded.  For those familiar °dONLNdÚ·÷Ì˛(    Ùwith the°dONLNd˚Ì<˘è(Z 'PREC' 103 °dONLNdÓè˙_)S&method of downloading PostScript code °dONLNd,Ó_˙˛)–(refer to Technical Note #192,°dONLNdK˚<€(#Z!Surprised in LaserWriter 5.2 and °dONLNdl˚€)ü Newer), the °dONLNdx˙C)>'feed'°dONLNd~˚C»)* resources are downloaded °dONLNdò˚»Ï)Öbefore°dONLNdû˚Ï˛)$ the°dONLNd£<â(0Z 'PREC' 103 °dONLNdÆâ•)M=resource.  In the case of background printing, the resources °dONLNdΕ˛(0√are copied into the°dONLNdˇ<!ì(=Zspool file.  Since °dONLNdì Ω)W'feed'°dONLNdΩ!Ú)*  resources °dONLNd#Ú!˛)53-8191 and -8190 are automatically downloaded by the°dONLNdW!<-:(IZ5LaserWriter, they must contain PostScript code.  The °dONLNdå!:-˛)˛)format of these PostScript resources is a°dONLNd∂-<9ø(UZstring of ASCII characters °dONLNd—-ø9˛)ÉAwithout any length byte or terminator.  The size of the string is°dONLNd9<E(aZ2determined by the size of the resource; there are °dONLNdE9E˛)„0no special size restrictions on these resources,°dONLNdvE<Q(mZ0and their only requirement is that they contain °dONLNd¶EQ˛)‚+PostScript code.  To make debugging easier,°dONLNd“Q<]‡(yZZyou should separate lines of PostScript using a carriage return character (13 or $0D hex).
  4942. °dONLNd-u<Ñ*'Don't Feed The Print Monster
  4943. °dONLNdJê<úg*    One last °dONLNdSêgú˛)+Qimportant note concerns the 6.1 version of the LaserWriter driver, shipped on the°dONLNd•ú<®"(ƒZ0Macintosh Printing Tools disk included with the °dONLNd’ú"®˛)Ê,Personal LaserWriter LS and StyleWriter.  In°dONLNd    ®<¥k(–Z=this version of the driver, the Feeder button will only work °dONLNd    ?®k¥˛(–âwhen Background printing is°dONLNd    [¥<¿?(‹Z6disabled.  There is a problem with the driver finding °dONLNd    ë¥?¿˛(‹]$the 'feed' resources when Background°dONLNd    ∂¿<Ãø(ËZMprinting is enabled.  This problem has been solved in the 7.0 version of the °dONLNd
  4944. ¿øÃ˛(Ë› driver which°dONLNd
  4945. Ã<ÿi(ÙZ:should be used instead of the 6.1 driver as soon as it is °dONLNd
  4946. JÃiÿ˛(Ùáavailable.  Since there is no°dONLNd
  4947. hÿ<‰ò(ZHworkaround for the problem, you don't really have to do anything except °dONLNd
  4948. ∞ÿò‰˛(∂for possibly noting it°dONLNd
  4949. «‰<‚( ZVin your documentation.  Any note should recommend upgrading to the 7.0 version of the °dONLNd ‰‚˛( driver°dONLNd $<¸õ(Zas soon as possible.
  4950. °dONLNd 9<#æ*'Driving Miss Lasey
  4951. °dONLNd L0<<Ã*Now that you have the two or °dONLNd i0Ã<Á)êthree °dONLNd o/Á;)'feed'°dONLNd u0<˛)*2 resources, the big question is installation.  How°dONLNd ®<<Ho(dZAshould you ship these things?  There are two methods.  The first °dONLNd È<oH˛(dçmethod involves licensing the°dONLNd H<T.(pZ1LaserWriter driver from Apple Software Licensing °dONLNd 8H.T˛)Ú'(SW.License on AppleLink).  This method°dONLNd `T<`Á(|Z]is only required for “turn-key” systems, where all installation is done for the user and you °dONLNd ΩTÁ`˛(|must°dONLNd ¬`<l¬(àZRship the LaserWriter driver as part of your product.  The second method, which is °dONLNd
  4952. `¬l˛(à‡ by and large°dONLNd
  4953. !l<xÈ(îZ'preferred as it requires no licensing, °dONLNd
  4954. HlÈx˛)≠<is to ship your resources in an installer application.  This°dONLNd
  4955. Öx<Ñ≤(†ZOapplication simply opens the LaserWriter file and adds the necessary resources. ¿X¿
  4956. *6PR 15 - Feeder Fodder(÷5) of 6(ÏZM.PR.FeederFodderˇ8◊#ˇ ˇˇˇˇ#◊ 
  4957. IR,Times
  4958. .+6-Macintosh Technical Notes /4/˘
  4959. °dONLNd)8a*'
  4960. Conclusion
  4961. °dONLNd DPå*OSo this should be all the information you need to implement the feed resources °dONLNdZDåP⁄(l™for your device.°dONLNdlP\Ç(x6MIf you intend to drive a sheet feeder through the LaserWriter’s serial port, °dONLNdπPÇ\⁄(x†be sure to contact°dONLNdÃ\hk(Ñ6FAdobe Systems, Inc. for the most current implementation and licensing °dONLNd\kh⁄(Ñâinformation.  Although°dONLNd)htÅ(ê6Jthe Feeder button could theoretically be used for other purposes, it will °dONLNdshÅt⁄(êüalways be labeled°dONLNdÖtÄG(ú6    “Feeder” °dONLNdétGÄ⁄)/Nby the LaserWriter driver.  Because of this consistency, developers should not°dONLNd›ÄåV(®6Eattempt to extend its functionality beyond support for sheet feeders.°dONLNd#∞ºÇ*0Further Reference: €4€˘°dONLNd6Ω*….+
  4962. •°dONLNd8Ω<…])8PostScript Language Reference Manual, Adobe Systems Inc.°dONLNdq…*’.(ÒH•°dONLNds…<’)&Technical Note M.IM.LWDriverSuprises —°dONLNdú’`·!+$ ' Surprises in LaserWriter 5.2 and Newer°dONLNdƒÌ˘\(6CPostScript is a registered trademark of Adobe Systems Incorporated. ¿4¿˘
  4963. (÷66) of 6(÷üPR 15 - Feeder Fodder+
  4964. M.PR.FeederFodderˇf◊#ˇ ˇˇˇˇ#◊°d WORDS †å°d WORDR…†Ç 
  4965. /ZÅ#
  4966.     0Ià:µú9"{    ˇˇˇˇˇˇˇˇ#†ƒ°d
  4967. ONLNf˛†å°d1drw2…-·_ġˇˇˇˇˇè°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˙ó@†ò,Times
  4968. .WIQkWIQk+]BNew Technical Notes†ô°ddrw2:°„†ó°d1drw2eÙġˇˇˇˇˇP°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚ÄE¿†ò
  4969. Ä({ïDeveloper Support†ô°ddrw2:°„†ó°d`drw2-ÔˇˇˇˇˇˇKÔ- Z  ffZ°d1drw2 ¿˙ÈˇˇˇˇˇˇK°ñ x°ddrw2:°ddrw2:$°d4drw2:0°öˇÙĆò
  4970. 0(UÔ†ô°ddrw2:°„†ó°d1drw2ÔÊ˙ˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:    °öˇ˝Ä†ò
  4971.     l+&    ®†ô°ddrw2:°„†ó°d1drw2Â-¯yˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚Ä%†ò
  4972. BÄ(Z\    Macintosh†ô°ddrw2:°„†ó†ç°ddrw2D†É°dWORD†ç
  4973. IR.°dONLNdo<Ç6(úZPR 16 - Fun With PrJobMerge
  4974. °dONLNdÅ<ês*Printing
  4975. °dONLNd&ú<®t* Revised by:°dONLNd2úÑ®–)HMatt Deatherage°dONLNdBúŒ®˛(ƒÏMay 1992°dONLNdK®<¥q(–Z Written by:°dONLNdW®Ñ¥T)H(Scott “Zz” Zimmerman and Matt Deatherage°dONLNdÄ®≈¥˛(–„
  4976. March 1992°dONLNdã¿<Ã˛(ËZ#This Technical Note discusses some °dONLNdÆ¿˛Ã˛)¬1interesting behavior you’ll encounter while using°dONLNd‡Ã<ÿÄ(ÙZCPrJobMerge with the 7.0 and 7.1 versions of the LaserWriter driver.°dONLNd$ÿ<‰ë* Changes since °dONLNd2ÿ뉟)U March 1992:°dONLNd=ÿŸ‰˛)H<  Corrected the Vulcan-like “THPring” typo to correctly read°dONLNdz‰<∑( ZM“THPrint,” and changed a comment in the code to mean what I originally meant. X°dONLNd»
  4977. <Ï*&"Like many Printing Manager calls, ,
  4978. Courier°dONLNdÍ    Ï2)∞
  4979. PrJobMerge°dONLNdÙ
  4980. 27)F °dONLNdı
  4981. 7˛)&is implemented by the currently chosen°dONLNd<"‹(>Z!printer driver. This makes sense °dONLNd=‹"˙)†:after consideration—since the printer driver may store job°dONLNdw˙"˛(>-°dONLNdx"<.û(JZKspecific information anywhere in the print record, only the printer driver °dONLNd√"û.˛(Jºcan correctly merge°dONLNd◊.<:fi(VZ%this into a destination print record.°dONLNd˝G<S *+The LaserWriter driver’s implementation of °dONLNd(F RR)–
  4982. PrJobMerge°dONLNd2GRSÖ)F  has a few °dONLNd=GÖS˛)3bugs in versions 7.0 and°dONLNdVS<_P({Z7.1.
  4983. °dONLNd[w<Üñ*' Fun Thing #1
  4984. °dONLNdhì<üz*Historically, °dONLNdvízû¿)>
  4985. PrJobMerge°dONLNdÄì¿üé)F, hasn’t worked correctly in the LaserWriter °dONLNd¨ìéü˛)Œdriver. The driver does°dONLNdƒü<´À(«ZXnot correctly merge all job-related data (like the number of copies requested) into the °dONLNdüÀ´˛(«È destination°dONLNd(´<∑V(”Zprint °dONLNd.´V∑˛)Vrecord, so printing multiple copies of multiple documents from the Finder isn’t really°dONLNdÖ∑<√Í(flZ%possible with the LaserWriter driver.°dONLNd´œ<€k*    The only °dONLNd¥œk€˛)/Ppossible workaround is to present a different job dialog for each document to be°dONLNd€<Áx(Z
  4986. printed, but °dONLNd€xÁ˛)<Mthis isn’t recommended—especially since the job dialog doesn’t tell you which°dONLNd`Á<Û“(Zdocument you’re about to print.
  4987. °dONLNdÄ <ñ*' Fun Thing #2
  4988. °dONLNdç&<20*4As if this wasn’t enough excitement for one driver, °dONLNd¡&02˛)Ù*in versions 7.0 and 7.1 of the LaserWriter°dONLNdÏ3<?[([Zdriver °dONLNdÛ2[>°)
  4989. PrJobMerge°dONLNd˝3°?))F actually manages to destroy °dONLNd3)?fl)à(all the job-specific information in the °dONLNdB3fl?˛)∂source°dONLNdI?<Kw(gZHprint record after it doesn’t copy it into the destination print record.°dONLNdíW<cœ*There is a workaround for this °dONLNd±Wœc˛)ì;problem—make a copy of the source print record and pass the°dONLNdÌd<pj(åZcopy to °dONLNdıcjo∞).
  4990. PrJobMerge°dONLNdˇd∞pB)F. If you pass the copy to °dONLNdcBoà)í
  4991. PrJobMerge°dONLNd#dàp¨)F, you °dONLNd)d¨p˛)$can just replace°dONLNd:p<|Ç(ôZ
  4992. PrJobMerge°dONLNdDqÇ}|)F1 with your own routine that makes a copy, merges °dONLNduq|}˛)˙it into the destination, and°dONLNdí}<âÜ(•Zdisposes of the °dONLNd¢}Üâ˛)JOcopy. This will work for all printer drivers, although it’s necessary only with°dONLNdÚâ<ïÓ(±Z&version 7.0 of the LaserWriter driver. ¡X¡
  4993. *%PR 16 - Fun With PrJobMerge(÷1) of 2(ÏZM.PR.FunWithPrJobMergeˇ°¿Ù%%DSIDICT:_cv
  4994. currentdict /bu known {bu}if
  4995. userdict /_cv known not{userdict /_cv 30 dict put}if
  4996. _cv begin
  4997. /bdf{bind def}bind def
  4998. currentscreen/cs exch def/ca exch def/cf exch def
  4999. /setcmykcolor where{/setcmykcolor get /cvcmyk exch def}{/cvcmyk{1 sub 4 1 roll 3{3 index add neg dup 0 lt{pop 0}if 3 1 roll}repeat setrgbcolor pop}bdf }ifelse
  5000. /ss{//cf //ca //cs setscreen}bdf
  5001. /stg{ss setgray}bdf
  5002. /strgb{ss setrgbcolor}bdf
  5003. /stcmyk{ss cvcmyk}bdf
  5004. /min1{dup 0 eq{pop 1}if}bdf
  5005. end
  5006. currentdict /bn known {bn}if
  5007. †ø ≤◊#ˇ ˇˇˇˇ#◊ 
  5008. IR,Times
  5009. .+6-Macintosh Technical Notes /4/˘
  5010. °dONLNd)5¯*$0Such a procedure might look like this in Pascal:,
  5011. Courier
  5012.     °dONLNd1AL&*6PROCEDURE NewPrJobMerge(hPrintSrc,hPrintDst: THPrint);°dONLNdhU`;*    VAR°dONLNdp_jï*
  5013.         copyError: OSErr;°dONLNdäit§*
  5014.         hPrintTemp: THPrint;°dONLNdß}àE*        BEGIN°dONLNd±áí®*
  5015. P        hPrintTemp := hPrintSrc;  {make our own copy of the print record handle}°dONLNdëú*
  5016. 4        copyError := HandToHand(Handle(hPrintTemp));°dONLNd7õ¶+*
  5017. 7        PrSetError(copyError); {so we can get it later}°dONLNdo•∞€*
  5018. '        IF copyError = noErr THEN BEGIN°dONLNdóØ∫l*
  5019. D            {hPrintTemp is now a copy of the original source record}°dONLNd‹πƒ®*
  5020. P            PrJobMerge(hPrintTemp,hPrintDst); {This messes up hPrintTemp, but we°dONLNd-√Œ:*
  5021. :                                               don't care}°dONLNdhÕÿ«*
  5022. #        END; {if copyError = noErr}°dONLNdå◊‚≠*
  5023. Q        IF hPrintTemp <> NIL THEN DisposHandle(Handle(hPrintTemp)); {only a copy,°dONLNdfi·Ï£*
  5024. O                                                                     remember!}°dONLNd.Έ@*
  5025.     END;
  5026. °dONLNd7
  5027. 1*&'Don’t Go Overboard Trying to Solve This
  5028. °dONLNd_)5Ç*Although the bugs in °dONLNdt(Ç4»)j
  5029. PrJobMerge°dONLNd~)»5P)F in versions 7.0 and 7.1 of °dONLNdö)P5⁄)àthe LaserWriter driver make°dONLNd∂5Ad(]6certain kinds of °dONLNd«5dA⁄)LKprinting multiple documents impossible without device-specific workarounds,°dONLNdAMü(i6we strongly encourage you °dONLNd-AüM±)ánot°dONLNd0A±M/) to implement such code. °dONLNdIA/M⁄)~$Any code that tries to replicate the°dONLNdnNZU(v6 function of °dONLNdzMUYõ)=
  5030. PrJobMerge°dONLNdÑNõZ\)F" must by nature depend on how the °dONLNd¶N\Z⁄)¡LaserWriter driver stores°dONLNd¿Zf`(Ç6information in °dONLNdœZ`f⁄)HLthe print record, and this is a Bad Thing. The road to Compatibility Hell is°dONLNdfrú(é6paved with good intentions.°dONLNd8~ä    *5If you write your code as described in this Note, it °dONLNdm~    ä⁄)Ò*will behave properly when the bug is fixed°dONLNdòãó©(≥6without change on your part. °dONLNdµã©óî)ë-If you go overboard trying to write your own °dONLNd‚äîñ⁄)Î
  5031. PrJobMerge°dONLNdÌó£v(ø6Kfunction, your application is a prime candidate for compatibility problems.°dONLNd9«”Ç*0Further Reference: Ú4Ú˘°dONLNdL‘*‡.+
  5032. •°dONLNdN‘<‡ç)Inside Macintosh°dONLNd^‘ç‡2)Q!, Volume II, The Printing Manager ¡4¡˘
  5033. (÷62) of 2(÷{PR 16 - Fun With PrJobMerge+
  5034. M.PR.FunWithPrJobMergeˇ◊#ˇ ˇˇˇˇ#◊†Ç 
  5035. /ZÅ#
  5036.     0Ià:µú9"{    ˇˇˇˇˇˇˇˇ#†ƒ°d
  5037. ONLNf˛†å°d1drw2…-·_ġˇˇˇˇˇè°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˙ó@†ò,Times
  5038. .R…R…+]BNew Technical Notes†ô°ddrw2:°„†ó°d1drw2eÙġˇˇˇˇˇP°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚ÄE¿†ò
  5039. ({ïDeveloper Support†ô°ddrw2:°„†ó°d`drw2-ÔˇˇˇˇˇˇKÔ- Z  ffZ°d1drw2 ¿˙ÈˇˇˇˇˇˇK°ñ x°ddrw2:°ddrw2:$°d4drw2:0°öˇÙĆò
  5040. 0(UÔ†ô°ddrw2:°„†ó°d1drw2ÔÊ˙ˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:    °öˇ˝Ä†ò
  5041.     +&    ®†ô°ddrw2:°„†ó°d1drw2Â-¯yˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚Ä%†ò
  5042. (Z\    Macintosh†ô°ddrw2:°„†ó†ç°ddrw2D†É
  5043. IR.°dONLNdn<Åq(õZ#PR 17 - ImageWriter II Paper Motion
  5044. °dONLNd$Ä<ès*Printing
  5045. °dONLNd.õ<ßt* Revised by:°dONLNd;õ≈߲(√„
  5046. March 1988°dONLNdFß<≥q(œZ Written by:°dONLNdRßÑ≥–)HGinger Jernigan°dONLNdbßÀ≥˛(œÈ
  5047. April 1986°dONLNdmø<Àı(ÁZ)The purpose of this technical note is to °dONLNdñøıÀ˛)π3answer the many questions asked about why the paper°dONLNd À<◊(ÛZ,moves the way it does on the ImageWriter II. X°dONLNd˜<¸*%%Many people have asked why the paper °dONLNd¸˛)ƒ2is rolled backward at the beginning of a Macintosh°dONLNdO¸<($Z2print job on the ImageWriter II. First, note that °dONLNdŸ˛)‡/this only happens with pin-feed paper (i.e. not°dONLNd±<Ü(0ZGwith hand-feed or the sheet-feeder) and only at the beginning of a job.°dONLNd˘ <,â*It is not a bug, °dONLNd
  5048.  â,˛)MLand it is not malicious programming. It is simply that users are told in the°dONLNdW,<8m(TZ
  5049. manual to °dONLNda,m8˛)1Uload pin-feed paper with the top edge at the pinch-rollers, making it easy to rip off°dONLNd∑8<D®(`ZOthe printed page(s) without wrecking the paper that is still in the printer or °dONLNd8®D˛(`Δhaving to roll the°dONLNdD<Pˆ(lZ\paper up and down manually. At the end of every job, the software makes sure that the paper °dONLNduDˆP˛(lis°dONLNdxP<\ô(xZMleft in this position, leaving the print-head roughly an inch from the edge. °dONLNd≈Pô\˛(x∑If something is to be°dONLNd€\<h`(ÑZ?printed higher than that, the paper has to be rolled backwards.°dONLNdu<Å:*6As you are probably aware, the “printable rectangle” (,
  5050. Courier°dONLNdQt:Ä])˛rPage°dONLNdVu]Å)#!) reported to the application by °dONLNdwuŞ)ìthe°dONLNd{Å<çT(©Z<print code begins 1/2 inch from the top edge, not one inch. °dONLNd∑ÅTç˛(©r#The reason for that is that we want°dONLNd€ç<ô*(µZ1a document to print exactly the same way whether °dONLNd ç*ô˛)Ó,you are printing on the ImageWriter I or II.°dONLNd9ô<•Ô(¡Z^On the ImageWriter I, the paper starts with the print-head 1/2 inch from the top edge, so the °dONLNdóôÔ•˛(¡
  5051. top°dONLNdõ¶<≤I(ŒZof °dONLNdû•I±l)
  5052. rPage°dONLNd£¶l≤)#' is at that position for both printers.°dONLNdÀæ< e(ÊZ    There is °dONLNd‘æe ˛))Tno way to eliminate the reverse-feed action, because the user would have to load the°dONLNd) <÷π(ÚZMpaper a different way AND the software would have to know that this was done.°dONLNdx‚<Ó¨*QIncidentally, in addition to the paper motion described above, there is also the °dONLNd…‚¨Ó˛(
  5053.  “burp.” This is a°dONLNd€Ó<˙ª(ZV1/8-inch motion back and forth to take up the slop in the printer’s gear-train. It is °dONLNd1Óª˙˛(Ÿ
  5054. needed on the°dONLNd?˙<q("ZAold-model printer, and there is debate about whether or not it’s °dONLNdÄ˙q˛("èneeded on ALL ImageWriter°dONLNdö<®(.ZLIIs, or only some, or none. The burp has been in and out of the ImageWriter °dONLNdÊ®˛(.ΔII code in various°dONLNd˘<∑(:Zreleases; right now it’s in. ¡X¡
  5055. *ú#PR 17 - ImageWriter II Paper Motion(÷1) of 1(ÏZM.PR.ImageWriterIIPaperˇ°¿Ù%%DSIDICT:_cv
  5056. currentdict /bu known {bu}if
  5057. userdict /_cv known not{userdict /_cv 30 dict put}if
  5058. _cv begin
  5059. /bdf{bind def}bind def
  5060. currentscreen/cs exch def/ca exch def/cf exch def
  5061. /setcmykcolor where{/setcmykcolor get /cvcmyk exch def}{/cvcmyk{1 sub 4 1 roll 3{3 index add neg dup 0 lt{pop 0}if 3 1 roll}repeat setrgbcolor pop}bdf }ifelse
  5062. /ss{//cf //ca //cs setscreen}bdf
  5063. /stg{ss setgray}bdf
  5064. /strgb{ss setrgbcolor}bdf
  5065. /stcmyk{ss cvcmyk}bdf
  5066. /min1{dup 0 eq{pop 1}if}bdf
  5067. end
  5068. currentdict /bn known {bn}if
  5069. †øº◊#ˇ ˇˇˇˇ#◊°d WORDS †å°d WORDR…†Ç 
  5070. /ZÅ#
  5071.     0Ià:µú9"{    ˇˇˇˇˇˇˇˇ#†ƒ°d
  5072. ONLNf˛†å°d1drw2…-·_ġˇˇˇˇˇè°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˙ó@†ò,Times
  5073. .WIQkWIQk+]BNew Technical Notes†ô°ddrw2:°„†ó°d1drw2eÙġˇˇˇˇˇP°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚ÄE¿†ò
  5074. Ä({ïDeveloper Support†ô°ddrw2:°„†ó°d`drw2-ÔˇˇˇˇˇˇKÔ- Z  ffZ°d1drw2 ¿˙ÈˇˇˇˇˇˇK°ñ x°ddrw2:°ddrw2:$°d4drw2:0°öˇÙĆò
  5075. 0(UÔ†ô°ddrw2:°„†ó°d1drw2ÔÊ˙ˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:    °öˇ˝Ä†ò
  5076.     l+&    ®†ô°ddrw2:°„†ó°d1drw2Â-¯yˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚Ä%†ò
  5077. BÄ(Z\    Macintosh†ô°ddrw2:°„†ó†ç°ddrw2D†É°dWORD†ç
  5078. IR.°dONLNdo<Ç≤(úZ PR 18 - The °dONLNd o≤Dz)v&Effect of Spool-a-page/Print-a-page on°dONLNd3Å<î∫(ÆZShared Printers
  5079. °dONLNdCì<¢s*Printing
  5080. °dONLNdMÆ<∫t* Revised by:°dONLNdZÆ≈∫˛(÷„
  5081. March 1988°dONLNde∫<Δq(‚Z Written by:°dONLNdq∫ÑΔÃ)HGinger Jenigan°dONLNdÄ∫ŒΔ˛(‚ÏMay 1987°dONLNdâ“<fiÀ(˙ZPThis technical note discusses drawbacks of using the spool-a-page/ print-a-page °dONLNdŸ“Àfi˛(˙È    method of°dONLNd„fi<Íe(Z    printing. X°dONLNdÌ<Ë*%RThe “spool-a-page/print-a-page” method of printing prints each page of a document °dONLNd?˲(+as a°dONLNdD<œ(8Z separate job instead of calling ,
  5082. Courier°dONLNddœ)ì    PrPicFile°dONLNdmi)? to print the entire °dONLNdÇi˛)[picture file. Many applications°dONLNd¢<(è(DZCadopted this method of printing to avoid running out of disk space °dONLNdÂè(˛(D≠while the ImageWriter°dONLNd˚(<4Æ(PZdriver was spooling the °dONLNd(Æ4˛)rEdocument to disk. As long as you are printing to a directly connected°dONLNdY4<@(\Z)ImageWriter, you’re fine, but if you are °dONLNdÇ4@˛)‘.printing to remote or shared devices (like the°dONLNd±@<L¬(hZAppleTalk ImageWriter and °dONLNdÀ@¬L˛)ÜAthe LaserWriter), this method may create significant problems for°dONLNd
  5083. L<Xe(tZ    the user.°dONLNdd<pÃ*UWhen a job is initiated by the application, the driver establishes a connection with °dONLNdldÃp˛(åÍ the printer°dONLNdxp<|Ö(òZvia AppleTalk. °dONLNdápÖ|˛)IMWhen the job is completed, the driver closes the connection, allowing another°dONLNd’|<àr(§ZDjob the opportunity to print. If each page is a job in itself, then °dONLNd|rà˛(§êthe connection is closed and°dONLNd6à<î!(∞Z-reopened between each page, allowing another °dONLNdcà!î˛)Â-application to print between the pages of the°dONLNdëî<†Õ(ºZSdocument, which, as you might imagine, could present a significant problem. If two °dONLNd‰îÕ†˛(ºÎ
  5084. people are°dONLNdÔ†<¨r(»Z printing to °dONLNd˚†r¨˛)6Nthe same AppleTalk ImageWriter at the same time and their applications use the°dONLNdJ¨<∏¶(‘ZK“spool-a-page/print-a-page” method of printing, the pages of each document °dONLNd喝∏˛(‘ƒwill be interleaved°dONLNd©∏<ƒ{(‡Zat the printer.°dONLNdπ–<‹ß*IAlthough there are good reasons for using this method of printing, it is °dONLNd–ß‹˛(¯≈only useful for a°dONLNd‹<ËG(Z:directly connected printer. From a compatibility point of °dONLNdN‹GË˙(e&view, this method of printing is built°dONLNdt‹˙˲)≥-°dONLNduË<ÙI(Z5in device dependence. Also, this method could create °dONLNd™ËIÙ˛(g#serious problems for other types of°dONLNdŒÙ<`(Zremote °dONLNd’Ù`˛)$Qdevices. Therefore, we are recommending that applications avoid using this method°dONLNd'< v((Z?indiscriminately. You should check available disk space to see °dONLNdfv ˛((îhow much room you have°dONLNd} <](4Zbefore °dONLNdÑ ]˛)!Vyou print. If there isn’t enough space for your entire document, then print as much as°dONLNd€<$”(@ZMyou can (to minimize the interleaving) before starting another job. Whenever °dONLNd(”$˛(@Ò    possible,°dONLNd2$<0Δ(LZapplications should use the °dONLNdN$Δ0˛)ä;print loop described on page II-155 in The Printing Manager°dONLNdä0<<n(XZ chapter of °dONLNdï0n<ø)2Inside Macintosh°dONLNd•0ø<√)Q.°dONLNdß`<l¶(àZFurther Reference: ãXã°dONLNd∫mNyR+
  5085. •°dONLNdºm`y≤)Printing Manager°dONLNdÕyNÖR(°l•°dONLNdœy`Ö")$Technical Note M.IM.LaserWriterOpt —°dONLNd˜ÖÑëW+$ )Optimizing for the LaserWriter—Techniques ¡X¡
  5086. (÷ZBPR 18 - The Effect of Spool-a-page/Print-a-page on Shared Printers(÷1) of 1(ÏZ M.PR.Spoolerˇ°¿Ù%%DSIDICT:_cv
  5087. currentdict /bu known {bu}if
  5088. userdict /_cv known not{userdict /_cv 30 dict put}if
  5089. _cv begin
  5090. /bdf{bind def}bind def
  5091. currentscreen/cs exch def/ca exch def/cf exch def
  5092. /setcmykcolor where{/setcmykcolor get /cvcmyk exch def}{/cvcmyk{1 sub 4 1 roll 3{3 index add neg dup 0 lt{pop 0}if 3 1 roll}repeat setrgbcolor pop}bdf }ifelse
  5093. /ss{//cf //ca //cs setscreen}bdf
  5094. /stg{ss setgray}bdf
  5095. /strgb{ss setrgbcolor}bdf
  5096. /stcmyk{ss cvcmyk}bdf
  5097. /min1{dup 0 eq{pop 1}if}bdf
  5098. end
  5099. currentdict /bn known {bn}if
  5100. †øH◊#ˇ ˇˇˇˇ#◊†Ç 
  5101. /ZÅ#
  5102.     0Ià:µú9"{    ˇˇˇˇˇˇˇˇ#†ƒ°d
  5103. ONLNf˛†å°d1drw2…-·_ġˇˇˇˇˇè°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˙ó@†ò,Times
  5104. .R…R…+]BNew Technical Notes†ô°ddrw2:°„†ó°d1drw2eÙġˇˇˇˇˇP°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚ÄE¿†ò
  5105. ({ïDeveloper Support†ô°ddrw2:°„†ó°d`drw2-ÔˇˇˇˇˇˇKÔ- Z  ffZ°d1drw2 ¿˙ÈˇˇˇˇˇˇK°ñ x°ddrw2:°ddrw2:$°d4drw2:0°öˇÙĆò
  5106. 0(UÔ†ô°ddrw2:°„†ó°d1drw2ÔÊ˙ˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:    °öˇ˝Ä†ò
  5107.     +&    ®†ô°ddrw2:°„†ó°d1drw2Â-¯yˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚Ä%†ò
  5108. (Z\    Macintosh†ô°ddrw2:°„†ó†ç°ddrw2D†É
  5109. IR.°dONLNdn<Å](õZ!PR 19 - Using Laser Prep Routines
  5110. °dONLNd"Ä<ès*Printing
  5111. °dONLNd,õ<ßt* Revised by:°dONLNd9õ≈߲(√„
  5112. March 1988°dONLNdDß<≥q(œZ Written by:°dONLNdPßÑ≥–)HGinger Jernigan°dONLNd`ßœ≥˛(œÌ    July 1987°dONLNdkø<ÀÖ(ÁZFThis technical note addresses the issues involved in depending on the °dONLNd±øÖÀ˛(Á£procedures and constants°dONLNd À<◊Ë(ÛZ%defined in the Laser Prep dictionary. X°dONLNd<¸s*%BWhen you are writing an application that uses PostScript heavily, °dONLNd2s¸˛(ëit is very tempting to call the°dONLNdR¸< ($Zprocedures already defined in °dONLNdp¸ ˛)éAthe Laser Prep dictionary, rather than taking up the space in the°dONLNd≤<i(0Z=printer’s memory with PostScript procedures of your own. Or, °dONLNdÔi˛(0á if a procedure in the dictionary°dONLNd< †(<Zdoesn’t do what you °dONLNd$† ˛)dJneed it to do, it is tempting to go in and change it to do what you really°dONLNdo <,W(HZwant.°dONLNdu8<D *(Unfortunately, we cannot guarantee that °dONLNdù8 D˛)œ/either the name or the function of a particular°dONLNdÕD<PL(lZ4procedure in the dictionary will stay the same when °dONLNdDLP˛(lj"the LaserWriter driver changes. In°dONLNd$P<\$(xZ.addition, some procedures may become obsolete °dONLNdRP$\˛)Ë*and go away when the driver changes. Since°dONLNd}\<h≈(ÑZthe Laser Prep dictionary is °dONLNdö\≈h˛)â?considered part of the source for the LaserWriter driver, Apple°dONLNd⁄h<tà(êZGreserves the right to make any changes to it that are deemed necessary.°dONLNd"Ä<åÀ*MBecause we cannot guarantee the permanence of the contents of the Laser Prep °dONLNdoÄÀå˛(®È dictionary,°dONLNd{å<òj(¥Z=relying on its contents can pose a significant compatibility °dONLNd∏åjò˛(¥àproblem. If you rely on the°dONLNd‘ò<§;(¿Z6procedures defined in the Laser Prep dictionary, your °dONLNd
  5113. ò;§˛)ˇ)application will have to be revised every°dONLNd4§<∞(ÃZ-time Apple releases a new LaserWriter driver.°dONLNdbº<»µ*PIf you feel that you absolutely must use or modify procedures in the Laser Prep °dONLNd≤ºµ»˛(‰”dictionary, you°dONLNd¬»<‘W(Zmust °dONLNd«»W‘~)always°dONLNdÕ»~‘)'" check the version that is loaded °dONLNdÔ»‘˛)†.into the printer before you print. This allows°dONLNd‘<‡π(¸ZMyour application to take appropriate action if the version of the dictionary °dONLNdk‘π‡˛(¸◊
  5114. that has been°dONLNdy‡<ÏI(Z8downloaded to the printer isn’t one that you know about.
  5115. °dONLNd≤<é*'.How To Check The Laser Prep Dictionary Version
  5116. °dONLNd·<+˜*'To determine the version of Laser Prep °dONLNd˜+˛)ª5that the printer may contain, you have to communicate°dONLNd>+<7
  5117. (SZ*with the printer using the Printer Access °dONLNdh+
  5118. 7˛)Œ.Protocol (PAP); you can’t just send your query°dONLNdó7<C_(_Z>through the LaserWriter driver because there is no way to get °dONLNd’7_C˛(_}an answer back. The object code°dONLNdıC<O™(kZJand documentation for PAP are available from Apple’s Licensing department.°dONLNd@[<g£*JTo determine whether the dictionary has been downloaded and whether it is °dONLNdä[£g˛(É¡the right one, send°dONLNdûg<s
  5119. (èZ-the following PostScript code to the printer: ¡X¡
  5120. *G!PR 19 - Using Laser Prep Routines(÷1) of 3(ÏZM.PR.UsingLaserPrepRoutinesˇ°¿Ù%%DSIDICT:_cv
  5121. currentdict /bu known {bu}if
  5122. userdict /_cv known not{userdict /_cv 30 dict put}if
  5123. _cv begin
  5124. /bdf{bind def}bind def
  5125. currentscreen/cs exch def/ca exch def/cf exch def
  5126. /setcmykcolor where{/setcmykcolor get /cvcmyk exch def}{/cvcmyk{1 sub 4 1 roll 3{3 index add neg dup 0 lt{pop 0}if 3 1 roll}repeat setrgbcolor pop}bdf }ifelse
  5127. /ss{//cf //ca //cs setscreen}bdf
  5128. /stg{ss setgray}bdf
  5129. /strgb{ss setrgbcolor}bdf
  5130. /stcmyk{ss cvcmyk}bdf
  5131. /min1{dup 0 eq{pop 1}if}bdf
  5132. end
  5133. currentdict /bn known {bn}if
  5134. †øf◊#ˇ ˇˇˇˇ#◊ 
  5135. IR,Times
  5136. .+6-Macintosh Technical Notes /4/˘,
  5137. Courier
  5138.     °dONLNd<(†+$%!PS-Adobe-1.2 Query°dONLNd'<2|*
  5139. @%%Title: Query to establish Laser Prep ProcSet version propriety°dONLNdX1<<ı*
  5140. %%%?BeginProcSetQuery: AppleDict md xx°dONLNd;<Fn*
  5141.  
  5142. /md where{°dONLNdãE<Pπ*
  5143. /md get /av get cvi xx eq°dONLNd¶O<Zë*
  5144. {(1)}{(2)}ifelse}°dONLNdπY<dõ*
  5145. {(0)}ifelse = flush°dONLNdŒc<n√*
  5146. %%?EndProcSetQuery: unknown°dONLNdÎm<xU*
  5147. %%EOF
  5148. °dONLNdÒÉè&(¨6md°dONLNdÛÑ&ê‰)) is the name of the Apple dictionary and °dONLNdɉèÚ)æxx°dONLNdÑÚêé)  is the version number you want.°dONLNd?ù©7(≈6Note:°dONLNdDù7©;) °dONLNdEú;®P)/av°dONLNdHùP©≥) is a constant in the °dONLNd^ú≥®¡)cmd°dONLNd`ù¡©V) dictionary which contains the °dONLNdùV©∂)ïdictionary’s version°dONLNdî©<µõ(—Znumber. This is the °dONLNd®©õµ¥)_only°dONLNd¨©¥µ÷) object °dONLNd¥©÷µ∂)"-in the dictionary whose name and function are°dONLNd‚µ<¡µ(›Zguaranteed not to change.°dONLNd¸ÕŸH(ı6    From the °dONLNdÕHŸ⁄)0Sprinter you will receive a string. If the string returned begins with ‘%%’, it is a°dONLNdYŸÂB(6Status°dONLNd_⁄BÊK)*9 response. You can ignore it and wait for another string.°dONLNdôÚ˛¨(6TIf the response is ‘0’, the dictionary hasn’t been downloaded yet; you will need to °dONLNdÌÚ¨˛⁄(     determine°dONLNd˜˛
  5149. (&67how to best handle this situation for your application.°dONLNd/"§*YIf the response is ‘1’, the printer is loaded with the correct version of the dictionary.°dONLNdâ.:4*If the °dONLNdê.4:⁄)[response is ‘2’, then the dictionary exists but it isn’t the version you need. In this case°dONLNdÏ:Fo(b6you need to either °dONLNdˇ:oF⁄)WKlet the user know, or proceed in as standard a fashion as possible, without°dONLNdKFRZ(n6Ecalling or modifying routines contained in the Laser Prep dictionary.
  5150. °dONLNdëjy“*'Translating PostScript Files
  5151. °dONLNdÆÖë7*Some °dONLNd≥Ö7ë⁄)Xapplications interpret the PostScript files that are generated by the LaserWriter driver°dONLNd ëùW(π6:when the user presses command-F (generates document only) °dONLNdFëWù⁄(πuor command-K (generates°dONLNd^ù©‚(≈6(dictionary and document) after clicking °dONLNdÜù‚©⁄) -on the OK button in the Job dialog. A typical°dONLNd¥©µµ(—6Zapplication might translate these PostScript files into another page description language.°dONLNd¡Õã*This kind of application °dONLNd(¡ãÕ⁄)sFrequires intimate knowledge of the contents of the dictionary in order°dONLNdoÕŸ‹(ı6*to be able to do the translation, because °dONLNdôÕ‹Ÿ⁄)ƒ2it may have to expand the procedures used to their°dONLNd߈(6/actual values before it can then translate the °dONLNd˚ŸˆÂ⁄)fi,PostScript to another language. This poses a°dONLNd(ÂÒN(
  5152. 6Bsignificant compatibility problem. Since we cannot guarantee that °dONLNdjÂNÒ⁄(
  5153. lthe contents of the dictionary°dONLNdâÒ˝á(6Pwill not change, these types of applications will have to be revised every time °dONLNdŸÒá˝⁄(•we release a new°dONLNdÍ˝    Ã(%6Rversion of the LaserWriter driver. Also, there is no way to know which version of °dONLNd<˝Ã    ⁄(%Íthe°dONLNd@    K(16DLaserWriter driver generated the PostScript file the application is °dONLNdÑ    K⁄(1iinterpreting. You will have to°dONLNd£!¿(=6%require that a particular version of °dONLNd»¿!⁄)®9the LaserWriter driver be used to generate the PostScript°dONLNd    !-“(I6+files that your application will interpret.
  5154. °dONLNd    .ET¶*'Printer Independence
  5155. °dONLNd    C`l¡*&Applications that are written to take °dONLNd    i`¡l⁄)©;advantage of the routines in the Laser Prep dictionary are,°dONLNd    •lx(î61of course, highly device dependent. Being device °dONLNd    ÷lx⁄(î7%dependent can drastically reduce your°dONLNd    ¸xÑr(†6Ichances of being compatible with future printer-type devices. For a more °dONLNd
  5156. ExrÑ⁄(†êdetailed discussion of°dONLNd
  5157. \Ñêˆ(¨60this issue, please refer to Technical Note #122. ¡4¡˘
  5158. **2) of 3(÷i!PR 19 - Using Laser Prep Routines+M.PR.UsingLaserPrepRoutinesˇÇ◊#ˇ ˇˇˇˇ#◊ 
  5159. IR,Times
  5160. .+Z-Developer Support Center(-Ï
  5161. March 1988 /X/
  5162. °dONLNdA<M¶(iZFurther Reference: lXl°dONLNdNNZR+
  5163. •°dONLNdN`Z«)The Printing Manager°dONLNd*ZNfR(Çl•°dONLNd,Z`f)$PostScript Language Reference Manual°dONLNdQfNrR(él•°dONLNdSf`r")$Technical Note M.IM.DevIndPrinting —°dONLNdzrÑ~ +$ Device-Independent Printing ¡X¡
  5164. (÷Z!PR 19 - Using Laser Prep Routines(÷3) of 3(ÏZM.PR.UsingLaserPrepRoutinesˇ2◊#ˇ ˇˇˇˇ#◊°d WORDS †å°d WORDR…†Ç 
  5165. /ZÅ#
  5166.     0Ià:µú9"{    ˇˇˇˇˇˇˇˇ#†ƒ°d
  5167. ONLNf˛†å°d1drw2…-·_ġˇˇˇˇˇè°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˙ó@†ò,Times
  5168. .WIQkWIQk+]BNew Technical Notes†ô°ddrw2:°„†ó°d1drw2eÙġˇˇˇˇˇP°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚ÄE¿†ò
  5169. Ä({ïDeveloper Support†ô°ddrw2:°„†ó°d`drw2-ÔˇˇˇˇˇˇKÔ- Z  ffZ°d1drw2 ¿˙ÈˇˇˇˇˇˇK°ñ x°ddrw2:°ddrw2:$°d4drw2:0°öˇÙĆò
  5170. 0(UÔ†ô°ddrw2:°„†ó°d1drw2ÔÊ˙ˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:    °öˇ˝Ä†ò
  5171.     l+&    ®†ô°ddrw2:°„†ó°d1drw2Â-¯yˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚Ä%†ò
  5172. BÄ(Z\    Macintosh†ô°ddrw2:°„†ó†ç°ddrw2D†É°dWORD†ç
  5173. IR.°dONLNdo<Ç(úZPR 20 - LaserWriter °dONLNdoDz)≈Driver Surprises in 5.0 and°dONLNd0Å<îq(ÆZNewer
  5174. °dONLNd6ì<¢s*Printing
  5175. °dONLNd@Æ<∫t* Revised by:°dONLNdLÆÑ∫9)H!Mary Burke & Scott “Zz” Zimmerman°dONLNdnÆ∏∫˛(÷÷
  5176. February 1990°dONLNd|∫<Δq(‚Z Written by:°dONLNdà∫ÑΔÒ)HScott “Zz” Zimmerman°dONLNdù∫ÀΔ˛(‚È
  5177. April 1988°dONLNd®“<fi‚(˙ZXThis Technical Note describes some changes in version 5.0 and later LaserWriter drivers.°dONLNdfi<Í’* Changes since April 1988:°dONLNdfi’Í∫)ô/  Described a bug in 5.x which is fixed in 6.0 °dONLNdIfi∫Ͳ)Âand later, and°dONLNdXÍ<ˆI(Z;reiterated a warning about storing fonts in an application. !X!°dONLNdî<}*%CWith the release of LaserWriter 5.0 and background printing, a few °dONLNd◊}˛(7õchanges had to be made to°dONLNdÒ<'à(CZDthe LaserWriter driver.  Although these changes were transparent to °dONLNd5à'˛(C¶most applications, some°dONLNdM'<3ü(OZhave had problems.  °dONLNda'ü3˛)cHMost of these problems are related to use of unsupported features.  This°dONLNd™3<?¯([Z+Note details a partial list of the changes.
  5178. °dONLNd÷W<fê*'
  5179. No Mo’ Low
  5180. °dONLNd·r<~ç*Because of the °dONLNdrç~˛)QGproblems supporting both the high-level and low-level interfaces in the°dONLNd8~<ä(¶Z+background, the low-level interface is all °dONLNdc~ä˛)…2but removed.  Instead of the low-level calls being°dONLNdñã<ó„(≥Z$executed by the device driver, the _,
  5181. Courier°dONLNd∫ä„ñ")ß    PrCtlCall°dONLNd√ã"ó%)? °dONLNdƒã%ó˛)/procedure converts the call into its high-level°dONLNdÙó<£(øZXequivalent before execution.  This way, the LaserWriter driver has a common entry point °dONLNdLó£˛(øfor°dONLNdP£<ØC(ÀZ7both the low-level and high-level interfaces.  Because °dONLNdá£CØ˛(Àa'of this conversion, the low-level calls°dONLNdØØ<ªv(◊Z may not be °dONLNd∫Øvª˛):Nfaster than using the high-level equivalents.  In some cases, they may even be°dONLNd    ª<«`(„Zslower.°dONLNd”<fl·*XVersion 5.x of the LaserWriter driver also contains a bug with the low-level interface. °dONLNdi”·fl˛(˚ˇ If an°dONLNdpfl<Î(Z.application which uses the low-level Printing °dONLNdûflβ)◊0Manager interface encounters an error during the°dONLNdœÎ<˜‚(Z\course of the print job, the LaserWriter driver crashes before the application has a chance °dONLNd+΂˜˛(to see°dONLNd2˜<Æ(Zthe error.  Because the °dONLNdJ˜Æ˛)rEerror occurs inside the driver, there is no way for an application to°dONLNdê<ú(+ZKpredict or work around this problem.  The only solution to this problem is °dONLNd€ú˛(+∫to use the high-level°dONLNdÒ<Ö(7ZHPrinting Manager interface or to upgrade to version 6.0 or later of the °dONLNd9Ö˛(7£LaserWriter driver which°dONLNdR<'Ä(CZfixes this bug.
  5182. °dONLNdb?<Nœ*'Are You Convertible?
  5183. °dONLNdwZ<fO*8Whereas the conversion of the low-level calls should be °dONLNdØZOf˛(Çm$transparent, the conversion routines°dONLNd‘f<rñ(éZEmake some assumptions.  The conversion routines require a context in °dONLNdfñr˛(é¥which to operate; the°dONLNd/r<~(öZ+Printing Manager maintains a certain state °dONLNdZr~˛)”,while executing commands, and the conversion°dONLNdá~<ä/(¶Z2routines need access to this state to perform the °dONLNdπ~/ä˛)Û(conversion.  To provide this context, an°dONLNd‚ä<ñ≥(≤ZLapplication must have opened a document and a page.  This requirement means °dONLNd    .ä≥ñ˛(≤—that the original ¡X¡
  5184. (÷Z5PR 20 - LaserWriter Driver Surprises in 5.0 and Newer(÷1) of 4(ÏZM.PR.LaserWriterDriverSurpriseˇ°¿Ù%%DSIDICT:_cv
  5185. currentdict /bu known {bu}if
  5186. userdict /_cv known not{userdict /_cv 30 dict put}if
  5187. _cv begin
  5188. /bdf{bind def}bind def
  5189. currentscreen/cs exch def/ca exch def/cf exch def
  5190. /setcmykcolor where{/setcmykcolor get /cvcmyk exch def}{/cvcmyk{1 sub 4 1 roll 3{3 index add neg dup 0 lt{pop 0}if 3 1 roll}repeat setrgbcolor pop}bdf }ifelse
  5191. /ss{//cf //ca //cs setscreen}bdf
  5192. /stg{ss setgray}bdf
  5193. /strgb{ss setrgbcolor}bdf
  5194. /stcmyk{ss cvcmyk}bdf
  5195. /min1{dup 0 eq{pop 1}if}bdf
  5196. end
  5197. currentdict /bn known {bn}if
  5198. †ø˛◊#ˇ ˇˇˇˇ#◊ 
  5199. IR,Times
  5200. .+6-Macintosh Technical Notes /4/˘
  5201. °dONLNd)>*=method of using the low-level interface, which is documented °dONLNd=>)K(E\in °dONLNd@K)ù)
  5202. Inside Macintosh°dONLNdPù)÷)R , Volume II°dONLNd[÷)⁄)9-°dONLNd\)5 (Q62164, no longer works, as in the following example:,
  5203. Courier
  5204.     °dONLNdêA<Ls+$ PrDrvrOpen;°dONLNdùK<Vı*
  5205. %PrCtlCall(iPrDevCtl, lPrReset, 0, 0);°dONLNdƒU<`»*
  5206. { Send data to be printed. }°dONLNd‚_<jˇ*
  5207. 'PrCtlCall(iPrDevCtl, lPrPageEnd, 0, 0);°dONLNd i<tx*
  5208. PrDrvrClose;
  5209. °dONLNdã˝(ß61Instead, an application should use the following:
  5210.     °dONLNdKó<¢s+$ PrDrvrOpen;°dONLNdX°<¨ˇ*
  5211. 'PrCtlCall(iPrDevCtl, lPrDocOpen, 0, 0);°dONLNdÅ´<∂*
  5212. (PrCtlCall(iPrDevCtl, lPrPageOpen, 0, 0);°dONLNd´µ<¿»*
  5213. { Send data to be printed. }°dONLNd…ø<     *
  5214. )PrCtlCall(iPrDevCtl, lPrPageClose, 0, 0);°dONLNdÙ…<‘*
  5215. (PrCtlCall(iPrDevCtl, lPrDocClose, 0, 0);°dONLNd”<fix*
  5216. PrDrvrClose;
  5217. °dONLNd+Èıπ(6YThis method provides the Printing Manager with the context it needs to convert the calls.
  5218. °dONLNdÖ
  5219. ÿ*'Really Unsupported Features
  5220. °dONLNd°)5Â*$Sending data to the printer between °dONLNd≈)Â5˝)Õthe °dONLNd…(˝4C)
  5221. _PrOpenDoc°dONLNd”)C5a)F or °dONLNd◊(a4ß)
  5222. lPrDocOpen°dONLNd·)ß5⁄)F and the°dONLNdÍ5Ae(^6 _PrOpenPage°dONLNdı6eBy)M or °dONLNd˘5yAΔ) lPrPageOpen°dONLNd6ΔB⁄)M6 calls is not currently, and has never been supported.°dONLNd<BNW(j6DLaserWriter drivers prior to 5.0 interpreted this data, but 5.0 and °dONLNdÄBWN⁄(julater drivers ignore it.  To°dONLNdùNZÁ(v6+download an application-specific PostScript
  5223. °dONLNd»NÁVÌ(s®
  5224. °dONLNd…NÌZæ+, dictionary as a header with each document, °dONLNdıNæZ⁄)—Apple°dONLNd˚[g·(É6*recommends that the application provide a °dONLNd%Z·f )…'PREC'°dONLNd+[ gF)*
  5225.  resource of °dONLNd8ZFfi);ID = °dONLNd=Zif~)#103°dONLNd@[~g⁄), as is described in°dONLNdUgs)(è6the °dONLNdYg)sì)LaserWriter Reference°dONLNdngìsó)j.
  5226. °dONLNdpãöß(∂6A Little Less Control
  5227. °dONLNdܶ≤à*NFour of the six printer control calls originally supported by the LaserWriter °dONLNd‘¶à≤⁄(Œ¶driver have been°dONLNdÂ≤æç(⁄6discontinued due to lack °dONLNd˛≤çæ⁄)uDof use and difficulty supporting with background printing.  The four°dONLNdCæ ÷(Ê6'calls which follow were only supported °dONLNdjæ÷ ⁄)æ4by the LaserWriter driver and only documented in the°dONLNdü ÷®(Ú6LaserWriter Reference Manual°dONLNdª ®÷´)ê:
  5228.     °dONLNdø‚`Ìà(    ~°•° fill°dONLNd»‚®Ì⁄)H
  5229. °•° hexBuf°dONLNd”‚Ì")H
  5230. °•° printR°dONLNdfi‚8Ìj)H
  5231. °•° printF
  5232. °dONLNdÈ˘y(!6In addition to these °dONLNd˛˘y™)a calls, the °dONLNd    ¯™‘)1stdBuf°dONLNd˘‘⁄)*6 call is also affected.  There are two versions of the°dONLNdFB(.6stdBuf°dONLNdLBÌ)*% call depending upon the sign of the °dONLNdqÌ)´bytes°dONLNdvV)# parameter.  If °dONLNdÜVy)Fbytes°dONLNdãy|)# °dONLNdå|⁄)is negative, the text°dONLNd¢X(;6passed to the °dONLNd∞XÇ)@stdBuf°dONLNd∂Ç()*& call is converted to PostScript text °dONLNd‹(⁄)¶%before being sent to the LaserWriter.°dONLNd+m(G6This conversion °dONLNdm+⁄)UFmeans that special PostScript characters in the text are preceded by a°dONLNdZ+7ü(S6PostScript escape character. °dONLNdw+ü7⁄)áA In addition, characters with an ASCII value greater than 128 are°dONLNdπ7C´(_6Vconverted to octal before being sent to the LaserWriter.  This version of the call is °dONLNd7´C⁄(_…    no longer°dONLNdCOK(k6
  5233. supported.°dONLNd$[gP*
  5234. If the bytes °dONLNd1[Pg⁄)8Vparameter is positive, the text passed to the call is sent directly to the LaserWriter°dONLNdàgs…(è6\without conversion and interpreted as PostScript instructions.  This version of the call is °dONLNd‰g…s⁄(èÁstill°dONLNdÍsé(õ6Osupported, but there is one more problem.  When an application first opens the °dONLNd    9sé⁄(õ¨low-level driver°dONLNd    JÄå/(®6(via °dONLNd    O/ã|) _PrDrvrOpen°dONLNd    ZÄ|å})M3) with background printing enabled, no clip region °dONLNd    çÄ}å⁄(®õis defined.  If the ¡4¡˘
  5235. (÷65PR 20 - LaserWriter Driver Surprises in 5.0 and Newer(÷‡2) of 4(Ï6M.PR.LaserWriterDriverSurpriseˇ¶◊#ˇ ˇˇˇˇ#◊ 
  5236. IR,Times
  5237. .+Z-Developer Support Center(-‚
  5238. February 1990 /X/
  5239. °dONLNd<*e(FZAapplication then begins sending PostScript to the driver via the ,
  5240. Courier°dONLNdAe)è(FÉstdBuf°dONLNdGè*ˆ)* call, all of the output °dONLNd`ˆ*˛)gis°dONLNdc*<6ˇ(RZ*clipped, and only a blank page is printed.°dONLNdéB<N0*4To prevent this problem, the application must force °dONLNd¬B0N˛)Ù,a clip region to be sent to the LaserWriter.°dONLNdN<Z(vZ]The region is sent by the driver when it receives its first drawing command.  Unfortunately, °dONLNdMNZ˛(vthe°dONLNdQ[<g¬(ÉZdriver does not consider the °dONLNdnZ¬fÏ)ÜstdBuf°dONLNdt[Ïg)* call °dONLNdz[g˛)2to be a drawing command.  To force the clip region°dONLNd≠h<t(êZ,on the printer, the application can use the °dONLNdŸgsF)ƒ
  5241. iPrBitsCtl°dONLNd„hFtâ)F call to print a °dONLNdÙhât˛)Csmall bitmap outside the°dONLNd
  5242. t<Ä‘(úZ"printable area of the page.  This °dONLNd/t‘IJ)ò?call does not have any effect on the document, but it fires the°dONLNdoÄ<å’(®Zbottleneck routine and causes °dONLNdçÄ’å˛)ô:a definition of the clip region.  Since the clip region is°dONLNd»ç<ô´(µZreinitialized at each call °dONLNd„ç´ô∏)oto °dONLNdÊå∏ò)
  5243. lPrPageOpen°dONLNdÒçô˛)M4, the application should send the bitmap once at the°dONLNd&ö<¶`(¬Z    start of °dONLNd/ö`¶s)$;each page.  If any other printer control calls precede the °dONLNdjôs•ù(¬ëstdBuf°dONLNdpöù¶˛)* call, the application°dONLNdá¶<≤⁄(ŒZ!does not need to send the bitmap.
  5244. °dONLNd© <Ÿ‰*'Background Preparations
  5245. °dONLNd¡Ê<ÚS*The °dONLNd≈ÂSÒ¬)'PREC' ID = 201°dONLNd‘ʬÚö)o& mechanism only works when background °dONLNd˙ÊöÚ˛)ÿprinting is disabled.°dONLNdÚ<˛(ZZThis limitation is because of difficulties finding the resource under MultiFinder.  Since °dONLNdkÚ˛˛(the°dONLNdo˛<
  5246. u(&Z option only °dONLNd{˛u
  5247. ˛)9Pworks in the foreground, and since there is no way for an application to know if°dONLNdÃ
  5248. <Æ(2ZObackground printing is enabled, an application should avoid using this feature.
  5249. °dONLNd.<=‰*'Fonts In An Application?
  5250. °dONLNd5I<Us*
  5251. There are °dONLNd?IsU˛)7Itwo problems when printing application fonts with the LaserWriter driver.°dONLNdäU<aç(}ZApplication fonts°dONLNdõUça
  5252. )Q are fonts that are stored in °dONLNdπU
  5253. a˛)Ä4the resource fork of the application’s resource file°dONLNdÓa<m(âZ2rather than being stored in the System file.  The °dONLNd am˛)„.first problem occurs when the application font°dONLNdOm<yÙ(ïZ'has the same name as the application’s °dONLNdvmÙy˛)∏;resource file.  If this is the true, the LaserWriter driver°dONLNd≤y<Öπ(°ZWincorrectly assumes that the application’s resource file is a font file, and closes it °dONLNd    yπÖ˛(°◊after using the°dONLNdÖ<ë(≠Z)font.  To solve this problem, developers °dONLNdBÖë˛)»1should make sure the name of the application font°dONLNdtí<ûh(∫Z (i.e., the °dONLNdëhùí),'FOND'°dONLNdÖííû…)*D resource) is different from the name of the application’s resource °dONLNd…í…û˛(∫Á file.  Since°dONLNd÷û<™Î(ΔZ[the application can still be renamed by the user, developers should try to select a unique °dONLNd1ûΙ˛(Δ    font°dONLNd6™<∂‡(“Z!name.  If the font name does not °dONLNdW™‡∂˛)§7appear in a font menu, developers can simply append the°dONLNdè∑<√(flZapplication’s °dONLNdù∑√á)C2creator string onto the desired font name (i.e., '°dONLNdœ∂ᬲ(fl•MyApplicationFont°dONLNd·√<œ_(ÏZZZAP'°dONLNdʃ_–g)#).°dONLNdÈ‹<Ëü(ZThe second problem °dONLNd¸‹ü˲)cGwith application fonts only occurs when background printing is enabled.°dONLNd    EË<Ùô(ZWhen a print job is °dONLNd    YËôÙ˛)]Jperformed in the background, the LaserWriter driver writes all of the data°dONLNd    §Ù<(Z*to be printed into a file (called a spool °dONLNd    ŒÙ˛)¥;file) for printing at a later time by Print Monitor.  Since°dONLNd
  5254.  
  5255. < ‡((Z"the LaserWriter driver has no way °dONLNd
  5256. ,‡ ˛)§<of knowing when the file will actually be printed, it cannot°dONLNd
  5257. i <Ê(4Z'assume that the application will still °dONLNd
  5258. ê Ê˛)™:be open when the job is printed.  This is a problem if the°dONLNd
  5259. À<$Œ(@ZSapplication contains application fonts that Print Monitor needs at print time.  To °dONLNd Œ$˛(@Ï
  5260. solve this°dONLNd )$<0π(LZOproblem, the LaserWriter driver must determine whether the fonts needed by the °dONLNd x$π0˛(L◊application are°dONLNd à0<<Ç(XZLresident in the System file or in the application file.  If they are in the °dONLNd ‘0Ç<˛(X†application file, the driver°dONLNd Ò<<HØ(dZQmust copy them into the spool file so they are available to Print Monitor.  This °dONLNd B<ØH˛(dÕpractice can lead°dONLNd TH<Tù(pZMto very large spool files, as well as a significant loss of performance when °dONLNd °HùT˛(pªbackground printing°dONLNd µT<`~(|ZFis enabled.  To solve these and other user interface problems related °dONLNd ˚T~`˛(|úto application fonts, Apple°dONLNd
  5261. `<lÍ(àZ\strongly recommends that developers ship custom application fonts as suitcase files for the °dONLNd
  5262. s`Íl˛(àuser°dONLNd
  5263. xl<xΩ(îZto install in the System file. ¡X¡
  5264. *B5PR 20 - LaserWriter Driver Surprises in 5.0 and Newer(÷3) of 4(ÏZM.PR.LaserWriterDriverSurpriseˇ◊#ˇ ˇˇˇˇ#◊ 
  5265. IR,Times
  5266. .+6-Macintosh Technical Notes /4/˘
  5267. °dONLNd,°*Headin’ For Trouble
  5268. °dONLNd8D‡*+There is a minor bug in version 5.0 of the °dONLNd?8‡D⁄)»6LaserWriter driver that only affects applications that°dONLNdvDP(l6parse the PostScript °dONLNdãDP⁄)g@header downloaded by the driver with each document.  This header°dONLNdÃP\fi(x6'contains some PostScript comments that °dONLNdÛPfi\⁄)Δ2provide information about the current job.  One of°dONLNd&]it(Ö6these comments is ,
  5269. Courier°dONLNd8\th÷)\IncludeProcSet°dONLNdF]÷ia)b.  This comment takes three °dONLNdb]ai⁄)ãarguments:  a PostScript°dONLNd{iuı(ë6-dictionary name, a major version number, and °dONLNd®iıu⁄)›.a minor version number.  In version 4.0 of the°dONLNd◊uÅB(ù6?LaserWriter driver, the comment line looked like the following:
  5270.     °dONLNdç<ò˙+$&%% IncludeProcSet: (Appledict md) 65 0
  5271. °dONLNd?£Øˇ(À61Unfortunately, in version 5.0 of the LaserWriter °dONLNdp£ˇØ⁄)Á,driver, the last argument was removed.  This°dONLNdùت(◊63caused the comment line to look like the following:
  5272.     °dONLNd“«<“Î+$#%% IncludeProcSet (Appledict md) 66
  5273. °dONLNdˆ›È9(6<Since Adobe defined the comment to take three arguments, it °dONLNd2›9È⁄(W#is reasonable for applications that°dONLNdVÈıÃ(6Rparse the comments to expect three arguments; therefore, version 5.1 and later of °dONLNd®ÈÃı⁄(Íthe°dONLNd¨ı=(6>LaserWriter driver contain the correct version of the comment:
  5274.     °dONLNdÏ
  5275. <ı+$%%% IncludeProcSet (Appledict md) 67 0
  5276. °dONLNd/>ç(Z6No Go With Zero
  5277. °dONLNd"JVP*?Some applications want to force a font to be downloaded to the °dONLNdaJPV⁄(rnLaserWriter without actually°dONLNd~Vbd(~6Iprinting characters with the font.  This can be done in three easy steps:°dONLNd»nz"*1.°dONLNdÀn*z∑)Save the current pen position.°dONLNdÍzÜ"(¢62.°dONLNdÌz*Ü0)7Use any text drawing routine to draw a space character.°dONLNd%Üí"(Æ63.°dONLNd(Ü*íÎ)(Move the pen back to the saved position.°dONLNdQü´ä(«6Some applications use °dONLNdgûä™◊)r _DrawString°dONLNdrü◊´)M with a °dONLNdzü´e))empty string (e.g., °dONLNdéûe™«)eDrawString('')°dONLNdúü«´⁄)b) to°dONLNd°´∑t(”6Hforce the font downloading. Although this worked in LaserWriter drivers °dONLNdÈ´t∑⁄(”íup to 5.0, these calls°dONLNd∑√í(fl6Qare ignored by the 5.1 and later drivers.  The main reasons for this change were °dONLNdQ∑í√⁄(fl∞optimization of°dONLNda√œ(Î67performance and a reduction in the size of spool files.°dONLNdôÛˇÇ*0Further Reference: 4˘°dONLNd¨* .+
  5278. •°dONLNdÆ< ç)Inside Macintosh°dONLNdæç N)Q&, Volumes II & V, The Printing Manager°dONLNd *.(4H•°dONLNdÁ <Ã)LaserWriter Reference Manual°dONLNd$0\(L6CPostScript is a registered trademark of Adobe Systems Incorporated. ¡4¡˘
  5279. *ä5PR 20 - LaserWriter Driver Surprises in 5.0 and Newer(÷‡4) of 4(Ï6M.PR.LaserWriterDriverSurpriseˇV◊#ˇ ˇˇˇˇ#◊†Ç 
  5280. /ZÅ#
  5281.     0Ià:µú9"{    ˇˇˇˇˇˇˇˇ#†ƒ°d
  5282. ONLNf˛†å°d1drw2…-·_ġˇˇˇˇˇè°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˙ó@†ò,Times
  5283. .R…R…+]BNew Technical Notes†ô°ddrw2:°„†ó°d1drw2eÙġˇˇˇˇˇP°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚ÄE¿†ò
  5284. ({ïDeveloper Support†ô°ddrw2:°„†ó°d`drw2-ÔˇˇˇˇˇˇKÔ- Z  ffZ°d1drw2 ¿˙ÈˇˇˇˇˇˇK°ñ x°ddrw2:°ddrw2:$°d4drw2:0°öˇÙĆò
  5285. 0(UÔ†ô°ddrw2:°„†ó°d1drw2ÔÊ˙ˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:    °öˇ˝Ä†ò
  5286.     +&    ®†ô°ddrw2:°„†ó°d1drw2Â-¯yˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚Ä%†ò
  5287. (Z\    Macintosh†ô°ddrw2:°„†ó†ç°ddrw2D†É
  5288. IR.°dONLNdn<Åö(õZ)PR 21 - Pictures and the Printing Manager
  5289. °dONLNd*Ä<ès*Printing
  5290. °dONLNd4õ<ßq* Written by:°dONLNd@õÑßÃ)H Zz Zimmerman°dONLNdMõÀ߲(√È
  5291. April 1991°dONLNdX≥<ø◊(€ZUThis technical note described some problems and features of using Quickdraw pictures °dONLNd≠≥◊ø˛(€ıwith the°dONLNd∂ø<Àò(ÁZPrinting Manager.  °dONLNd…øòÀ˛)\JIn general, if your application prints Quickdraw pictures, you should read°dONLNdÀ<◊h(ÛZ
  5292. this note. X
  5293. °dONLNd¸< è*4 Introduction
  5294. °dONLNd,<#$*0Most applications support Quickdraw pictures to °dONLNd\$#˛)Ë+some degree.  They will allow you to import°dONLNdà#</j(KZ
  5295. or export °dONLNdí#j/˛).Tpicture files, as well as using the PICT resource format on the clipboard to support°dONLNdÁ/<;\(WZCut & °dONLNdÌ/\;˛) VPaste with other applications.  Unfortunately, there are some problems that occur with°dONLNdD;<GP(cZ=pictures at print time, and that's what I want to cover here.
  5296. °dONLNdÇ_<n∞*'You PICT When?
  5297. °dONLNdëz<ÜÒ*"One of the problems that comes up °dONLNd≥zÒܲ)µ3at print time is the use of picture comments.  Some°dONLNdÁÜ<íw(ÆZ
  5298. applications °dONLNdÙÜwí˛);Ustore their data in a native format, and only create pictures at print time to enable°dONLNdJí<û(∫Z/the use of picture comments.  For each page of °dONLNdyíû˛)‡-the document, they open a new picture, record°dONLNdßû<™Ñ(ΔZthe Quickdraw °dONLNdµûÑ™˛)HLcalls that described the document, along with any picture comments they want°dONLNd™<∂¥(“Zto use, and finally close °dONLNd™¥∂˛)xCthe picture.  When this is done, they call DrawPicture to print the°dONLNd`∂<¬Ñ(fiZGpicture, and then start the whole process over again for the next page.°dONLNd®Œ<⁄/*.This method is supported and fully compatible °dONLNd÷Œ/⁄˛)Û'with future system software, but is not°dONLNd˛⁄<Êˇ(Z'required.  The Printing Manager spools °dONLNd%⁄ˇÊ˛)√1each page of a document into a Quickdraw picture.°dONLNdXÊ<Úå(ZESince the Printing Manager already has a picture open, it is totally °dONLNdùÊåÚ˛(™legal to send a picture°dONLNdµÚ<˛Á(Z"comment (via the PicComment call) °dONLNd◊ÚÁ˛˛)´6in between calls to PrOpenPage and PrClosePage without°dONLNd˛<
  5299. (&Z%having them recorded in a picture.   °dONLNd3˛
  5300. ˛) -The Printing Manager has already replaced the°dONLNda
  5301. <’(2ZStdComment procedure with its °dONLNd
  5302. ’˛)ô:own anyway, so the PicComment call will be intercepted and°dONLNd∫<"í(>ZIsupported correctly by the Printing Manager.  If the only reason you are °dONLNdí"˛(>∞recording into pictures°dONLNd"<.ñ(JZBis so that you can use PicComments, you can avoid the overhead at °dONLNd]"ñ.˛(J¥print time by simply°dONLNdr.<:œ(VZsending the comments directly.
  5303. °dONLNdëR<a¥*'Feeling PICT On?
  5304. °dONLNd¢m<y*-Even if you aren't sending picture comments, °dONLNdœmy˛)·/you may still need to create a picture at print°dONLNdˇy<Ö>(°Z9time.  In general, you should try to create any pictures °dONLNd8y>Ö˛(°\'you need prior to calling PrOpen.  This°dONLNd`Ö<ëP(≠Z8is because there is no way to predict how much memory a °dONLNdòÖPë˛(≠n'particular printer driver will require. ¡X¡
  5305. (÷Z)PR 21 - Pictures and the Printing Manager(÷1) of 4(ÏZM.PR.PictAndPrintingˇ°¿Ù%%DSIDICT:_cv
  5306. currentdict /bu known {bu}if
  5307. userdict /_cv known not{userdict /_cv 30 dict put}if
  5308. _cv begin
  5309. /bdf{bind def}bind def
  5310. currentscreen/cs exch def/ca exch def/cf exch def
  5311. /setcmykcolor where{/setcmykcolor get /cvcmyk exch def}{/cvcmyk{1 sub 4 1 roll 3{3 index add neg dup 0 lt{pop 0}if 3 1 roll}repeat setrgbcolor pop}bdf }ifelse
  5312. /ss{//cf //ca //cs setscreen}bdf
  5313. /stg{ss setgray}bdf
  5314. /strgb{ss setrgbcolor}bdf
  5315. /stcmyk{ss cvcmyk}bdf
  5316. /min1{dup 0 eq{pop 1}if}bdf
  5317. end
  5318. currentdict /bn known {bn}if
  5319. †ø ◊#ˇ ˇˇˇˇ#◊ 
  5320. IR,Times
  5321. .+6-Macintosh Technical Notes /4/˘
  5322. °dONLNd)*3Instead, you need to make as much memory available °dONLNd3)⁄)ˇ*as possible.  If you are creating pictures°dONLNd^)57(Q6:with the Printing Manager open, the chances are good that °dONLNdò)75⁄(QUyou are using memory you can't°dONLNd∑5Ac(]6afford to waste.°dONLNd»MY¶* If you need to create a picture °dONLNdËM¶Y⁄)é<with the Printing Manager open, and memory is not a problem,°dONLNd%Ye-(Å6you °dONLNd)Y-e⁄)Zshould still be aware of some potential problems.  First of all, keep in mind the Printing°dONLNdÑeqi(ç6FManager receives data from the application by replacing the Quickdraw °dONLNd eiq⁄(çáGrafProcs stored in the°dONLNd‚q}S(ô6<GrafPort returned by PrOpenDoc.  One of these procedures is °dONLNdqS}⁄(ôqthe StdComment procedure°dONLNd7}â8(•6which °dONLNd=}8â⁄) Vis called each time the application calls the Quickdraw PicComment routine.  Since the°dONLNdîâï£(±6Printing Manager has these °dONLNdØâ£ï⁄)ã>routines patched, creating a picture in the Printing Manager's°dONLNdÓï°¸(Ω6%GrafPort can cause problems.  If you °dONLNd︰⁄)‰&must create a picture between calls to°dONLNd:°≠∞(…6SPrOpenPage/PrClosePage, you should be sure to set the port to a standard Quickdraw °dONLNdç°∞≠⁄(…ŒGrafPort°dONLNdñ≠π9(’6before °dONLNdù≠9π⁄)!Scalling OpenPicture.  Any GrafPort that was created by Quickdraw (as opposed to the°dONLNdÒπ≈∏(·6!Printing Manager) will work fine.°dONLNd—›é*PIf you do create a picture at print time, you may experience a syndrome we call °dONLNdc—é›⁄(˘¨'floating picture°dONLNdu›Èœ(6Scomments'.  That is, calls made by your application to the PicComment routine will °dONLNd»›œÈ⁄(Ìbe°dONLNdÀÈı≠(6Srecorded in a different order than you made them.  This will usually cause them to °dONLNdÈ≠ı⁄(À
  5323. effect the°dONLNd)ı®(6wrong part of the picture, and °dONLNdHı®⁄)ê@lead to endless confusion.  The best solution to this problem is°dONLNdâ
  5324. ()67to create any pictures that your application will need °dONLNd¿
  5325. 3)˜before°dONLNdΔ3
  5326. Δ)$ opening the Printing Manager.
  5327. °dONLNdÂ%4G(P6,Scaling Pictures - Mountains from Mole Hills
  5328. °dONLNd@Ll*DAnother problem is a basic problem with pictures that seems to show °dONLNdV@lL⁄(häup more at print time.°dONLNdnLX0(t6The °dONLNdrL0X⁄)Rproblem concerns the scaling of pictures using the destination rectangle passed to°dONLNd≈Xd}(Ä6JDrawPicture.  This method will work for most pictures, but problems arise °dONLNdX}d⁄(Äõwith more complex°dONLNd!dpÂ(å6/pictures, and for pictures that contain text.  °dONLNdPdÂp⁄)Õ0The problem is the method that Quickdraw uses to°dONLNdÅp|ò(ò6scale the text stored within °dONLNdûpò|⁄)ÄCpictures.  When scaling, Quickdraw tries to handle the text scaling°dONLNd‚|à;(§6>intelligently by changing the size of the font being used, as °dONLNd |;à⁄(§Y!opposed to just scaling the bits.°dONLNdCàî£(∞6TUnfortunately, the widths used by bitmapped fonts are not always linear (ie. the 12 °dONLNdóà£î⁄(∞¡ point width°dONLNd£î†(º66isn't exactly 1/2 of the 24 point width).  Because of °dONLNdŸî†⁄)ˆ*this, you can run into problems with lines°dONLNd    †¨b(»6Iof text getting slightly longer or shorter as the picture is scaled.  In °dONLNd    M†b¨⁄(»Ämany cases, the error is°dONLNd    f¨∏∏(‘6Uinsignificant, but if you are trying to draw a line of text that fits exactly into a °dONLNd    ª¨∏∏⁄(‘÷box (a°dONLNd    ¬∏ƒΩ(‡6#spreadsheet cell for example), you °dONLNd    Â∏Ωƒ⁄)•;might be surprised to see the line of text extending beyond°dONLNd
  5329. !ƒ–ª(Ï6#the box when the picture is scaled.°dONLNd
  5330. E‹Ëú*There can also be problems °dONLNd
  5331. `‹úË⁄)Ñ?when using certain picture comments or imbedded PostScript.  In°dONLNd
  5332. †ËÙö(6the case of the TextCenter °dONLNd
  5333. ªËöÙ⁄)ÇApicture comment, you specify an offset to the center of rotation.°dONLNd
  5334. ˛Ù (68This offset is usually based on the metrics of the font °dONLNd 6Ù ⁄(>&being used.  If you scale the picture,°dONLNd ] ”((6%Quickdraw decides to use a different °dONLNd Ç” ⁄)ª5font, and the offset you originally specified will be°dONLNd ∏ E(46
  5335. incorrect.°dONLNd √$0é*The easiest way to solve °dONLNd ‹$é0⁄)vGthese problems is to scale the picture yourself.  Especially if you are°dONLNd $0<∑(X6Ztrying to scale by a large amount.  For example, some applications create a picture at 72 °dONLNd ~0∑<⁄(X’dpi (ie.°dONLNd á<Hÿ(d6)dots per inch), and then scale it to 288 °dONLNd ∞<ÿH⁄)¿5dpi for printing by simply increasing the destination°dONLNd ÊHT˙(p6.rectangle by 4x.  This is asking a lot of the °dONLNd
  5336. H˙T⁄)‚,system, and will result in the text problems°dONLNd
  5337. AT`Ö(|6Pdescribed above.  Instead, you should either draw the picture into its original °dONLNd
  5338. ëTÖ`⁄(|£frame, and let the°dONLNd
  5339. §`lé(à6RPrinting Manager handle scaling it to the resolution of the device, or handle the °dONLNd
  5340. ˆ`él⁄(à¨scaling yourself°dONLNdlx»(î6[by parsing the picture and playing it back opcode by opcode instead of calling DrawPicture. ¡4¡˘
  5341. *B2) of 4(÷M)PR 21 - Pictures and the Printing Manager+NM.PR.PictAndPrintingˇ2◊#ˇ ˇˇˇˇ#◊ 
  5342. IR,Times
  5343. .+Z-Developer Support Center(-
  5344. April 1991 /X/
  5345. °dONLNd<)Ÿ(EZ!One last thing to watch for when °dONLNd!Ÿ)˛)ù@scaling pictures is integer overflows.  It's usually pretty rare°dONLNdb)<51(QZ4that you will overflow a coordinate when creating a °dONLNdñ)15˛)ı+Quickdraw picture, but it is not so hard to°dONLNd¬5<Aå(]Zdo when scaling °dONLNd“5åA˛)PKa picture.  For example, some applications will draw something offscreen to°dONLNdA<MÉ(iZmake sure the °dONLNd,AÉM˛)GMPrinting Manager has configured the clip region and other related structures.°dONLNd{M<YÈ(uZVThey usually do this by moving the cursor to (-32767,-32767), and then draw a pixel.  °dONLNd—MÈY˛(uThis°dONLNd÷Y<e[(ÅZ=works fine to initialize the Printing Manager, and the pixel °dONLNdY[e˛(Åy"isn't actually seen on the output.°dONLNd7e<q§(çZNThe problem occurs when you try to scale this picture.  If you try to make it °dONLNdÖe§q˛(ç¬bigger, Quickdraw°dONLNdóq<}¶(ôZIwill adjust to coordinate (-32767,-32767) which will end up overflowing. °dONLNd‡q¶}˛(ôƒ The only way to°dONLNdÒ}<âÁ(•Z^solve these problems is to look for these kinds of operations in the picture before trying to °dONLNdO}Áâ˛(•scale°dONLNdUâ<ïú(±Zit with DrawPicture.
  5346. °dONLNdj≠<ºó*'3Pictures Within Pictures–Is Nesting the Best Thing?
  5347. °dONLNdû»<‘£*LOne cool feature of Quickdraw pictures is the ability to nest them easily.  °dONLNdÍ»£‘˛(¡Basically, you can°dONLNd˝‘<‡R(¸Zcall °dONLNd‘R‡˛)POpenPicture, and then call DrawPicture with multiple pictures, and when you call°dONLNdS‡<Ïπ(ZMClosePicture, they will all have been recorded into one picture.  Very cool. °dONLNd†‡πÏ˛(◊  The problem°dONLNd≠Ï<¯_(Zcomes °dONLNd≥Ï_¯˛)#Lwhen you start using the Begin/End form of picture comments.  There are some°dONLNd¯<â( Zcomments like °dONLNd¯â˛)MFPostScriptBegin/PostScriptEnd, and TextBegin/TextEnd that have a begin°dONLNdU<Ç(,Z
  5348. comment that °dONLNdbDz)FEis followed by an end comment.  When using these comments, it is very°dONLNd®<Ì(8Z%important to make sure that you have °dONLNdÕÌ˛)±9an end for each begin that you have sent.  If the nesting°dONLNd<(ê(DZJgets off, you will, at the least, get incorrect output, though it is more °dONLNdQê(˛(DÆlikely that the Printing°dONLNdj(<4i(PZManager °dONLNdr(i4˛)-Twill actually crash.  If your application is generating picture comments, it is very°dONLNd«4<@(\Z-simple to make sure that you have an end for °dONLNdÙ4@˛)÷0each begin.  But when nesting a picture that you°dONLNd%@<Lj(hZ@have imported from another application, it is important to know °dONLNde@jL˛(hàhow its comments will interact°dONLNdÑL<Xs(tZ with yours.°dONLNdêd<p’*UIn most cases, you can simply call DrawPicture to render the picture to the Printing °dONLNdÂd’p˛(åÛManager°dONLNdÌp<|Î(òZ\and you don't have to worry.  But if you are creating a picture for export, you may have to °dONLNdIpÎ|˛(ò    nest°dONLNdN|<à»(§ZXmultiple pictures from multiple creators into the same picture to be exported.  If this °dONLNd¶|»à˛(§Ê is the case,°dONLNd≥à<îR(∞Zit is °dONLNdπàRî˛)Qimportant to make sure that all of your begin comments have matching end comments°dONLNd     î<†`(ºZbefore°dONLNd    î`†Ä)$A attempting to insert another picture.  If this is done, you can °dONLNd    RîƲ(ºûinsert the imported picture°dONLNd    n†<¨”(»ZWwithout having to worry about the comments it contains.  If all of your begin/ends are °dONLNd    ≈†”¨˛(»Òmatched,°dONLNd    Œ¨<∏^(‘Z?you can assume that the imported picture will be just as valid.°dONLNd
  5349. ƒ<–°*On the other hand, if °dONLNd
  5350. $ƒ°–˛)eGyou have a begin comment, and want to insert a picture before inserting°dONLNd
  5351. l–<‹M(¯Zthe °dONLNd
  5352. p–M‹˛)Yappropriate end comment, you must parse the picture to be inserted to make sure it is not°dONLNd
  5353.  ‹<Ë∏(ZRusing the same comment pair.  If it is, and you insert it, you will have problems.°dONLNd Ù<ì*So make sure that °dONLNd /Ùì˛)WLall your begins and ends are matched, and don't try to insert other pictures°dONLNd |< ¯((Z&between begin/end pairs of comments.  °dONLNd ¢¯ ˛)º7If you find that you have to insert a picture between a°dONLNd ⁄ <á(4ZFpair of begin/end comments, you must parse the picture to be inserted °dONLNd   á˛(4•to make sure that it does°dONLNd :<$¡(@Znot use the same comments.
  5354. °dONLNd U<<K*' Penalty for Quickdraw - Clipping
  5355. °dONLNd vW<c*/Here's a subtle fact about Quickdraw pictures. °dONLNd •Wc˛)fi. If you call OpenPicture, and then record some°dONLNd ‘c<o>(ãZ7drawing operations, and you don't explicitly specify a °dONLNd
  5356. c>o˛(ã\'clipping region, Quickdraw will specify°dONLNd
  5357. 3o<{ó(óZMone for you.  In fact, Quickdraw will use the last clip region stored in the °dONLNd
  5358. Äoó{˛(óµGrafPort that you are°dONLNd
  5359. ñ{<áo(£Z>using when you call OpenPicture.  This has been a surprise to °dONLNd
  5360. ‘{oá˛(£çmany a developer when they ¡X¡
  5361. (÷Z)PR 21 - Pictures and the Printing Manager(÷3) of 4(ÏZM.PR.PictAndPrintingˇ ◊#ˇ ˇˇˇˇ#◊ 
  5362. IR,Times
  5363. .+6-Macintosh Technical Notes /4/˘
  5364. °dONLNd)s*Krecord a picture, and a big piece of it ends up missing when they draw it. °dONLNdKs)⁄(Eë This isn't specific to°dONLNdc)5Õ(Q6^print time, it can happen on the screen too, but it happens enough that it's worth mentioning.
  5365. °dONLNd¬M\s*'
  5366. D' Resolution
  5367. °dONLNd–ht®*If you've read Technical Note °dONLNdÓh®t⁄)ê<#275, Features of 32 Bit Quickdraw 1.2, you probably noticed°dONLNd+tÄ(ú65the new font and resolution information.  Basically, °dONLNd`tÄ⁄)˜)fonts are now stored in pictures by name,°dONLNdäÄå…(®6Tnot by ID.  This means that fonts stored in pictures will be displayed correctly on °dONLNdfiÄ…å⁄(®Áany°dONLNd‚åò3(¥67Macintosh without fonts remapping to other faces.  The °dONLNdå3ò⁄(¥Q!other new addition to the picture°dONLNd;ò§ (¿6:format is horizontal and vertical resolution information. °dONLNduò §⁄(¿>( Applications that create pictures using°dONLNdû§∞˜(Ã6/the new OpenCPicture call will be able to tell °dONLNdÕ§˜∞⁄)fl.Quickdraw the native resolution of the picture°dONLNd¸∞º¥(ÿ6#data.  So if you're a scanner that °dONLNd∞¥º⁄)ú>is scanning at 200 dpi, you will be able to store your data at°dONLNd^º»ß(‰6200 dpi (instead of scaling it °dONLNd}ºß»⁄)è=to 72 dpi first).  When an application subsequently opens the°dONLNdª»‘7(6<picture, it can determine the picture's resolution and take °dONLNd˜»7‘⁄(U!the necessary steps to display it°dONLNd‘‡{(¸6correctly (ie. scaling °dONLNd0‘{‡⁄)cGdown for display on the 72 dpi screen, or scaling up for display on 300°dONLNdx‡ϵ(6"dpi devices like the LaserWriter).
  5368. °dONLNdõa*'
  5369. Conclusion
  5370. °dONLNd¶+7*>Quickdraw pictures can be used successfully at print time, if °dONLNd‰7+⁄(GU you avoid the problems described°dONLNd+7ò(S6Qabove.  Although there is a little overhead required by some of the workarounds, °dONLNdV+ò7⁄(S∂
  5371. most are very°dONLNdd7C(_6Ksimple to implement, and will help you avoid future compatibility problems.°dONLNd∞gsÇ*0Further Reference: í4í˘°dONLNd√t*Ä.+
  5372. •°dONLNd≈t<Ä])8PostScript Language Reference Manual, Adobe Systems Inc.°dONLNd˛Ä*å.(®H•°dONLNdÄ<å"),LaserWriter Reference Manual, Addison-Wesley°dONLNd-ò§\(¿6CPostScript is a registered trademark of Adobe Systems Incorporated. ¡4¡˘
  5373. (÷64) of 4(÷M)PR 21 - Pictures and the Printing Manager+NM.PR.PictAndPrintingˇ*◊#ˇ ˇˇˇˇ#◊†Ç 
  5374. /ZÅ#
  5375.     0Ià:µú9"{    ˇˇˇˇˇˇˇˇ#†ƒ°d
  5376. ONLNf˛†å°d1drw2…-·_ġˇˇˇˇˇè°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˙ó@†ò,Times
  5377. .R…R…+]BNew Technical Notes†ô°ddrw2:°„†ó°d1drw2eÙġˇˇˇˇˇP°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚ÄE¿†ò
  5378. ({ïDeveloper Support†ô°ddrw2:°„†ó°d`drw2-ÔˇˇˇˇˇˇKÔ- Z  ffZ°d1drw2 ¿˙ÈˇˇˇˇˇˇK°ñ x°ddrw2:°ddrw2:$°d4drw2:0°öˇÙĆò
  5379. 0(UÔ†ô°ddrw2:°„†ó°d1drw2ÔÊ˙ˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:    °öˇ˝Ä†ò
  5380.     +&    ®†ô°ddrw2:°„†ó°d1drw2Â-¯yˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚Ä%†ò
  5381. (Z\    Macintosh†ô°ddrw2:°„†ó†ç°ddrw2D†É
  5382. IR.°dONLNdn<ÅÑ(õZPR 22 - °dONLNdnÑŞ)H+pIdle Proc (or how to let users know what’s°dONLNd4Ä<ì0(≠Zgoing on during print time…)
  5383. °dONLNdQí<°s*Printing
  5384. °dONLNd[≠<πq* Written by:°dONLNdg≠Ñπ)HPete “Luke” Alexander°dONLNd}≠Àπ˛(’È
  5385. April 1991°dONLNdà≈<—^(ÌZ;This Technical Note discusses how to defensively program a °dONLNd√≈^—˛(Ì| pIdle procedure to work with the°dONLNd‰—<›ß(˘ZRmajority of print drivers in existence today, and how to install it at print time. X
  5386. °dONLNd7ˆ<è*( Introduction
  5387. °dONLNdD<t*CWhen using a pIdle procedure at print time, there are a few things °dONLNdát˛(9íthat one should remember to°dONLNd£<)ò(EZbe compatible with °dONLNd∂ò)˛)\Lthe printer drivers that are available today.  This Technical Note discusses°dONLNd)<5Â(QZ[installing a pIdle procedure at the right time and the things to remember when writing one.
  5388. °dONLNdaM<\‰*'Installing The pIdle Proc
  5389. °dONLNd{h<t *SLet's start by installing the pIdle procedure at the right time.  You must install °dONLNdŒh t˛(êË
  5390. your pIdle°dONLNdŸu<Å(ùZ/procedure into the print record before calling ,
  5391. Courier°dONLNdtÄW)‹    PrOpenDoc°dONLNduWÅÖ)?
  5392. .  If you °dONLNduÖŞ).do not install your pIdle°dONLNd5Ç<éÃ(™Zprocedure before your call to °dONLNdSÅÃç )ê    PrOpenDoc°dONLNd\Ç éÇ)?, the printer driver does °dONLNdvÇÇé˛)wnot give the application's°dONLNdëé<ö≈(∂ZpIdle procedure any time.  °dONLNd¨é≈ö˛)â=The following code fragments demonstrate installing the pIdle°dONLNdÍö<¶ø(¬Zprocedure in the right place:°dONLNd≤<æÉ*
  5393. MPW Pascal
  5394.     °dONLNd <’P*    °dONLNd P’\)<<°dONLNd \’∞) D more print loop would appear above, see Tech Note #161 for details °dONLNd] ∞’º(ÒŒ>>°dONLNd`fi<È©(ZI    {**  Install a pointer to your pIdle proc into your print record. **}°dONLNd™Ú<˝|*@    PrintingStatusDialog := GetNewDialog(257, NIL, POINTER(-1));°dONLNdθ<w*
  5395. ?    thePrRecHdl^^.prJob.pIdleProc := @checkMyPrintDialogButton;°dONLNd+<6*2    thePrPort := PrOpenDoc(thePrRecHdl, NIL, NIL);°dONLNd^$</P*    °dONLNdb$P/\)<<°dONLNdd$\/∞) D more print loop would follow below, see Tech Note #161 for details °dONLNd®$∞/º(KŒ>>
  5396. °dONLNd´F<Rh(nZMPW C
  5397.     °dONLNd±^<iH*      °dONLNd∑^HiT) <<°dONLNdπ^Ti®) D more print loop would appear above, see Tech Note #161 for details °dONLNd˝^®i¥(ÖΔ>>°dONLNdr<}Æ(ôZJ    /**  Install a pointer to your pIdle proc into your print record.  **/ ¡X¡
  5398. *=PPR 22 - pIdle Proc (or how to let users know what’s going on during print time…)(÷1) of 3(ÏZM.PR.pIdleProcˇ°¿Ù%%DSIDICT:_cv
  5399. currentdict /bu known {bu}if
  5400. userdict /_cv known not{userdict /_cv 30 dict put}if
  5401. _cv begin
  5402. /bdf{bind def}bind def
  5403. currentscreen/cs exch def/ca exch def/cf exch def
  5404. /setcmykcolor where{/setcmykcolor get /cvcmyk exch def}{/cvcmyk{1 sub 4 1 roll 3{3 index add neg dup 0 lt{pop 0}if 3 1 roll}repeat setrgbcolor pop}bdf }ifelse
  5405. /ss{//cf //ca //cs setscreen}bdf
  5406. /stg{ss setgray}bdf
  5407. /strgb{ss setrgbcolor}bdf
  5408. /stcmyk{ss cvcmyk}bdf
  5409. /min1{dup 0 eq{pop 1}if}bdf
  5410. end
  5411. currentdict /bn known {bn}if
  5412. †øÃ◊#ˇ ˇˇˇˇ#◊ 
  5413. IR,Times
  5414. .+6-Macintosh Technical Notes /4/˘,
  5415. Courier
  5416.     °dONLNd'2b*!B    PrintingStatusDialog = GetNewDialog(257, nil, (WindowPtr) -1);°dONLNdC1<S*
  5417. ?    (**thePrRecHdl).prJob.pIdleProc = checkMyPrintDialogButton;°dONLNdÉEP
  5418. *1    thePrPort = PrOpenDoc(thePrRecHdl, nil, nil);°dONLNdµYd,*    °dONLNdπY,d8)<<°dONLNdªY8då) D more print loop would follow below, see Tech Note #161 for details °dONLNdˇYådò(Ä™>>
  5419. °dONLNdo{(ó64For a complete printing loop that handles errors at °dONLNd6o{⁄)Ó.print time and makes all of the right calls to°dONLNde{áê(£6Nthe Printing Manager, refer to Technical Note #161, A Print Loop That Cares...
  5420. °dONLNd¥üÆJ*')Things To Remember About pIdle Procedures
  5421. °dONLNdfi∫Δ"*It °dONLNd·∫"Δ⁄)
  5422. Zis extremely important to design and code your pIdle procedure as defensively as possible,°dONLNd=Δ“ó(Ó6Rthereby making sure that it works with as many printer drivers as possible.  This °dONLNdèΔó“⁄(Óµsection details°dONLNdü“fi+(˙68a few things to remember when creating pIdle procedures.°dONLNdÿ͈˘*%Saving And Restoring The Current Port°dONLNd˛í*It is extremely important °dONLNdí)zto save the printer driver’s °dONLNd5Z)â    GrafPort,°dONLNd>Z⁄)? upon entry to your pIdle°dONLNdXö(76Sprocedure and restore it upon exit.  Why? If you do not, the printer driver  would °dONLNd´ö⁄(7∏
  5423. draw into the°dONLNdπ'P(D6GrafPort°dONLNd¡P(Ò)8$ of your dialog box instead of it's °dONLNdÂÒ'0)°    GrafPort,°dONLNdÓ0(⁄)?"which will cause some bad results.°dONLNd)5|(Q6To save the printer’s °dONLNd((|4¥)dGrafPort°dONLNd0)¥5ª)8, °dONLNd2)ª5    )you should call °dONLNdB(    4A)N_GetPort°dONLNdJ)A5⁄)8 when entering your procedure.°dONLNdj6B(^6/Before you exit your procedure, you would call °dONLNdô5A<)Ï_SetPort°dONLNd°6<B¢)8 to set the port from °dONLNd∑6¢B⁄)f your dialog°dONLNd√CO≠(k6!box back to the printer driver’s °dONLNd‰B≠NÂ)ïGrafPort°dONLNdÏCÂOs)8 (i.e., the one you saved with °dONLNd BsN´)é_GetPort°dONLNdC´O≥)8).°dONLNd[gJ(É63Saving And Restoring The Printer Driver’s Resources°dONLNdJs *5If the application changes the resource chain within °dONLNds ⁄)Ù*it's pIdle procedure, you want to save and°dONLNd™ã(ß64restore the printer driver’s resource chain.  Why?  °dONLNdfiã⁄(ß6&Some printer drivers assume that their°dONLNdãóˇ(≥6-resource chain does not change, but this may °dONLNd2ãˇó⁄)Á+not be true when the driver calls the pIdle°dONLNd^ó£Û(ø6*procedure installed by the application at °dONLNdàóÛ£⁄)€*print time.  To accomplish this task, call°dONLNd≥£Øe(Ã6 _CurResFile°dONLNdæ§e∞“)M, saving the ID of the °dONLNd’§“∞⁄)m7printer driver’s resource file at the beginning of your°dONLNd
  5424. ∞º8(ÿ6;pIdle procedure.  When you exit from your pIdle procedure, °dONLNdH∞8º⁄(ÿV"restore the resource chain back to°dONLNdkΩ…˘(Â63the printer driver’s resource chain with a call to °dONLNdûº˘»F)· _UseResFile°dONLNd©ΩF…J)M.°dONLNd≠’·◊(˝6&At this point, you might be wondering °dONLNd”’◊·⁄)ø3what might change the resource chain. If you called°dONLNd·Ìá(    6F_OpenResFile or _UseResFile (anything that would change the value of  °dONLNdM·áÌ⁄(    •the low memory°dONLNd\Ì˘ö(6global TopMapHdl) within °dONLNduÌö˘⁄)ÇBthe application's pIdle procedure, the chain would be changed.  If°dONLNd∏˘s(!6Iyou are not changing the resource chain, these calls would not be needed.°dONLNd    +*-Handling Errors From Within A pIdle Procedure°dONLNd    0*6/*You °dONLNd    4*/6î)should avoid calling °dONLNd    I)î5≈)ePrError°dONLNd    P*≈6⁄)1; within your pIdle procedure; errors that occur while it is°dONLNd    å6B
  5425. (^63executing are usually temporary, and serve only as °dONLNd    ø6
  5426. B⁄)Ú+internal flags for communication within the°dONLNd    ÎCOF(k6Bprinter driver—they are not intended for the application.  If you °dONLNd
  5427. -CFO©(kdabsolutely must call °dONLNd
  5428. BB©N⁄)cPrError°dONLNd
  5429. JO[ÿ(w6)within your idle procedure, and an error °dONLNd
  5430. sOÿ[⁄)¿6occurs, never abort printing within the idle procedure°dONLNd
  5431. ™[gö(É6Uitself.  Wait until the last called printing procedure returns, then check to see if °dONLNd
  5432. ˇ[ög⁄(É∏the error still°dONLNd gs—(è6`remains.  Attempting to abort printing within an idle procedure is a guarantee of certain death. ¡4¡˘
  5433. *G2) of 3)pPPR 22 - pIdle Proc (or how to let users know what’s going on during print time…)(Ï∑M.PR.pIdleProcˇé◊#ˇ ˇˇˇˇ#◊ 
  5434. IR,Times
  5435. .+Z-Developer Support Center(-
  5436. April 1991 /X/
  5437. °dONLNd)<52(QZ)Canceling Or Pausing The Printing Process°dONLNd*A<Mµ*If you install a procedure °dONLNdEAµM˛)yEfor handling requests to cancel printing, with an option to pause the°dONLNdãM<Y@(uZ-printing process, beware of timeout problems °dONLNd∏M@Y˛(u^!when printing to the LaserWriter.°dONLNd€Y<e{(ÅZ=Communication between the Macintosh and the LaserWriter must °dONLNdY{e˛(Åôbe maintained to prevent a°dONLNd3e<q`(çZ:job or a wait timeout.  If there is not any communication °dONLNdme`q˛(ç~for a period of time (over two°dONLNdåq<}‰(ôZZminutes), the printer times out and the print job terminates due to a wait  timeout.  Or, °dONLNdÊq‰}˛(ôif the°dONLNdÌ}<âƒ(•ZWprint job requires more than three minutes to print, the print job terminates due to a °dONLNdD}ƒâ˛(•‚ job timeout.°dONLNdRâ<ï’(±ZYSince, there is not a good method to determine to what type of printer an application is °dONLNd´â’ï˛(±Û    printing,°dONLNdµï<°Y(ΩZ<it is probably a good idea to document the possibility of a °dONLNdÒïY°˛(Ωw!LaserWriter timing out for a user°dONLNd°<≠5(…Z3who chooses to select “pause” for over two minutes.°dONLNdGπ<≈v*4Some Printer Drivers Do Not Support pIdle Procedures°dONLNd|—<›∑*Some printer drivers do °dONLNdî—∑›˛){@not support pIdle procedures, as they prefer to handle the pIdle°dONLNd’›<Èe(Z>procedure in their own manner without giving an application’s °dONLNd›eÈ˛(ÉpIdle procedure any time.  This°dONLNd3È<ı¬(ZOsituation should not be a problem as long as you do not assume that your pIdle °dONLNdÇȬı˛(‡ procedure is°dONLNdèı<
  5438. (Z-always called at print time.  Therefore, you °dONLNdºı
  5439. ˛)Œ2should only create your pIdle procedure to display°dONLNdÔ<
  5440. ø()ZSthe dialog box and respond to a user pausing, continuing, or canceling a print job.
  5441. °dONLNdC%<4Ö*'
  5442. Conclusion
  5443. °dONLNdN@<Lq*AWhen installing your pIdle proc, it must be installed before the °dONLNdè@qL˛(hèapplication calls PrOpenDoc.°dONLNd≠L<X√(tZNYou want to make sure that you save and restore the GrafPort , upon entry and °dONLNd˚L√X˛(t· exit of your°dONLNdX<dÒ(ÄZ'pIdle procedure, to make sure that the °dONLNd/XÒd˛)µ:printer driver will image into the correct port during the°dONLNdjd<p€(åZ print job.  Finally, if you are °dONLNdäd€p˛)ü6changing the resource chain by calling _OpenResFile or°dONLNd¡p<|¿(òZP_UseResFIle, you want to make sure that you save and restore the resource chain.°dONLNd†<¨¶*0Further Reference: ÀXÀ°dONLNd&≠NπR+
  5444. •°dONLNd(≠`π±)Inside Macintosh°dONLNd8≠±πV)Q!, Volume II, The Printing Manager°dONLNdZπN≈R(·l•°dONLNd\π`≈    )Technical Note M.IM.PrintLoop —°dONLNd~≈Ñ—+$  A Print Loop That Cares... ¡X¡
  5445. (÷ZPPR 22 - pIdle Proc (or how to let users know what’s going on during print time…)(÷3) of 3(ÏZM.PR.pIdleProcˇ"◊#ˇ ˇˇˇˇ#◊†Ç 
  5446. /ZÅ#
  5447.     0Ià:µú9"{    ˇˇˇˇˇˇˇˇ#†ƒ°d
  5448. ONLNf˛†å°d1drw2…-·_ġˇˇˇˇˇè°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˙ó@†ò,Times
  5449. .R…R…+]BNew Technical Notes†ô°ddrw2:°„†ó°d1drw2eÙġˇˇˇˇˇP°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚ÄE¿†ò
  5450. ({ïDeveloper Support†ô°ddrw2:°„†ó°d`drw2-ÔˇˇˇˇˇˇKÔ- Z  ffZ°d1drw2 ¿˙ÈˇˇˇˇˇˇK°ñ x°ddrw2:°ddrw2:$°d4drw2:0°öˇÙĆò
  5451. 0(UÔ†ô°ddrw2:°„†ó°d1drw2ÔÊ˙ˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:    °öˇ˝Ä†ò
  5452.     +&    ®†ô°ddrw2:°„†ó°d1drw2Â-¯yˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚Ä%†ò
  5453. (Z\    Macintosh†ô°ddrw2:°„†ó†ç°ddrw2D†É
  5454. IR.°dONLNdn<Åâ(õZ'PR 23 - Position-Independent PostScript
  5455. °dONLNd(Ä<ès*Printing
  5456. °dONLNd2õ<ßt* Revised by:°dONLNd?õ≈߲(√„
  5457. March 1988°dONLNdJß<≥q(œZ Written by:°dONLNdVßÑ≥Û)HScott "ZZ" Zimmerman°dONLNdkø<À(ÁZ+This technical note describes a method for °dONLNdñøÀ˛)fi.inserting position-independent PostScript into°dONLNd≈À<◊û(ÛZQuickDraw pictures. X°dONLNdŸ<¸e*%    There is °dONLNd‚e¸˛))Sa problem with pictures that contain PostScript code. Sometimes the PostScript code°dONLNd6¸<fi($Z%that is inserted into the picture is °dONLNd[¸fi˛)¢9dependent on the position of the picture on the page. The°dONLNdï<r(0Z@problem arises when these pictures are cut or copied from their °dONLNd’r˛(0êoriginal position, and pasted°dONLNdÛ< T(<Z9into another position or even into another document. The °dONLNd,T ˛(<r!PostScript code will not know the°dONLNdN <,N(HZ<new location of the picture, and will not execute correctly.°dONLNdã8<D>*6The solution for this problem, is to provide some way °dONLNd¡8>D˛(`\(for the PostScript code to determine the°dONLNdÍD<PØ(lZRcurrent location of the picture relative to the page that it is being printed on. °dONLNd<DØP˛(lÕThis is done by°dONLNdLP<\ì(xZCinserting QuickDraw calls to position the LaserWriter’s pen before °dONLNdèPì\˛(x±inserting the position°dONLNd¶\<h™(ÑZKdependent PostScript code. When the PostScript in the picture is executed, °dONLNdÒ\™h˛(Ñ»the LaserWriter’s°dONLNdh<tΩ(êZWpen location will be in a location relative to the position of the picture on the page.°dONLNd[Ä<åk*;The following example illustrates a method for positioning °dONLNdñÄkå˛(®âthe LaserWriter’s pen before°dONLNd≥å<òΔ(¥ZSinserting any PostScript code into the picture. The method uses QuickDraw calls to °dONLNdåΔò˛(¥‰ position the°dONLNdò<§…(¿ZLaserWriter’s pen, and will °dONLNd/ò…§˛)ç;work with any application that supports QuickDraw pictures.°dONLNdk§<∞£(ÃZJApplications do not have to be changed to be able to print pictures which °dONLNdµ§£∞˛(áuse this technique;°dONLNd…±<ΩÑ(ŸZnormal calls to ,
  5458. Courier°dONLNdŸ∞Ѻ—)H DrawPicture°dONLNd‰±—Ω)M  will work.°dONLNd <÷Q(ÚZThe °dONLNdÙ Q÷˛)Zfollowing code fragment will create a picture that contains PostScript to draw a rectangle°dONLNdO÷<‚ª(˛Zaround the picture’s frame:
  5459.     °dONLNdkÓ<˘E*5FUNCTION CreatePicture(pictureRect: Rect): PicHandle;°dONLNd£¯`~+$
  5460. CONST °dONLNdÆÑ
  5461. ˜+$
  5462. PostScriptBegin = 190; °dONLNd  ÑÌ*
  5463. PostScriptEnd = 191; °dONLNd‰Ñ!˜*
  5464. PostScriptHandle = 192;°dONLNd˛ `+t(G~VAR °dONLNd*Ñ5±+$
  5465.     PSString °dONLNd*Ã5˛)H
  5466. : Str255; °dONLNd 4Ñ?±([¢    PSHandle °dONLNd*4Ã?˛)H
  5467. : Handle; °dONLNd9>ÑI±(e¢    theError °dONLNdC>ÃIÙ)H: OSErr;°dONLNdNH`S~(o~BEGIN °dONLNdYRÑ]+$
  5468. (* Create a new Picture. *) °dONLNdz\Ñg[*
  5469. +CreatePicture := OpenPicture(pictureRect); °dONLNd¨f®q+$
  5470. ClipRect(pictureRect); ¡X¡
  5471. (÷Z'PR 23 - Position-Independent PostScript(÷1) of 3(ÏZM.PR.PositionIndependentPSˇ°¿Ù%%DSIDICT:_cv
  5472. currentdict /bu known {bu}if
  5473. userdict /_cv known not{userdict /_cv 30 dict put}if
  5474. _cv begin
  5475. /bdf{bind def}bind def
  5476. currentscreen/cs exch def/ca exch def/cf exch def
  5477. /setcmykcolor where{/setcmykcolor get /cvcmyk exch def}{/cvcmyk{1 sub 4 1 roll 3{3 index add neg dup 0 lt{pop 0}if 3 1 roll}repeat setrgbcolor pop}bdf }ifelse
  5478. /ss{//cf //ca //cs setscreen}bdf
  5479. /stg{ss setgray}bdf
  5480. /strgb{ss setrgbcolor}bdf
  5481. /stcmyk{ss cvcmyk}bdf
  5482. /min1{dup 0 eq{pop 1}if}bdf
  5483. end
  5484. currentdict /bn known {bn}if
  5485. †ø¬◊#ˇ ˇˇˇˇ#◊ 
  5486. IR,Times
  5487. .+6-Macintosh Technical Notes /4/˘,
  5488. Courier
  5489.     °dONLNd`(å+H<(* Set the pen size to 0,0 so the following Line will not *)°dONLNd='2(N6 °dONLNd@'`2d)H4(* be shown, it is only sent to position the pen.*) °dONLNdz1Ñ<≈+$
  5490.  
  5491. PenSize(0,0);°dONLNdãE`PÇ(l~:(* Move the QuickDraw pen to the first pixel inside the *)°dONLNd»O`Z_*
  5492. 3(* the picture’s frame.  This by itself will not *)°dONLNd˛Y`dA*
  5493. -(* change the LaserWriter’s pen location! *) °dONLNd/c`n2*
  5494. *MoveTo(pictureRect.left, pictureRect.top);°dONLNd^w`Ç}*9(* Force the LaserWriter’s pen location to match the  *) °dONLNdúÅÑåµ+$
  5495. =(* QuickDraw pen location.  Actually any drawing command, *) °dONLNdflï`†n(º~6(* such as LineTo or even DrawString will cause the *)°dONLNdü™(Δ6 °dONLNdü`™Ç)H:(* LaserWriter’s pen location to change.  This call to *) °dONLNdX©Ñ¥ó+$
  5496. 7(* the Line procedure only causes the coordinates of *)°dONLNdê≥æ(⁄6 °dONLNdì≥`æ})H9(* the above MoveTo to be flushed to the LaserWriter. *) °dONLNd—ΩÑ»¶+$
  5497. :(* Because of the PenSize call above, no Line is drawn. *)°dONLNd «“(Ó6 °dONLNd«`“í)H
  5498. Line(0,0);°dONLNd€`Ê-*)(* Reset the pen to its default size. *) °dONLNdKÂ`°*
  5499.  
  5500. PenSize(1,1);°dONLNd\˘`†*@(* The LaserWriter’s pen location has now been changed.  The *) °dONLNd†Ñ¶+$
  5501. :(* PostScript currentpoint operator will now return the *)°dONLNd€
  5502. (46 °dONLNdfi
  5503. `Z)H2(* location of the center pixel of the Picture. *)°dONLNd`"7*
  5504. +(* Get the PostScript ready to be sent. *) °dONLNdE!`,´*
  5505. (* currentpoint°dONLNdV!,Ã)ê,- push the current Point onto the stack. *) °dONLNdÖ+Ñ6∂(R¢
  5506. (* newpath°dONLNdí+6™)ê- Begin a new Line segment. *)°dONLNd±5@(\6 °dONLNd¥5`@ç)H    (* MoveTo°dONLNd¿5@÷)ê.- Move to the currentpoint we saved above. *) °dONLNdÒ?ÑJ‘(f¢(* nn nn rlineto°dONLNd?Jæ)ê"- frame the Picture with lines. *)°dONLNd&IT(p6 °dONLNd)I`Tç)H    (* stroke°dONLNd3I®T≠)H °dONLNd6ITT)H- Draw the frame. *)°dONLNdKS^(z6 °dONLNdNS`^ó)H PSString :=°dONLNd]]`hØ*
  5507. C'100 0 rlineto 0 100 rlineto -100 0 rlineto 0 -100 rlineto stroke '°dONLNd•g®r≠+H
  5508. ;°dONLNdßq|(ò6 °dONLNd™q`|ñ)H>PSString[length(PSString)] := CHR(13); (* Don’t forget CR. *) °dONLNdÌ{ÑÜ[+$
  5509. +theError:=PtrToHand(Ptr(ORD4(@PSString)+1),°dONLNdÖÃê]+H
  5510.   PSHandle,length(PSString));°dONLNd=èö(∂6 °dONLNd@è`ö)H&IF theError <> noErr THEN HandleError;°dONLNdj£`Æ_*3(* Send the PostScript code to the LaserWriter. *) °dONLNd†≠<∏Ê(‘Z"PicComment(PostScriptBegin,0,nil);°dONLNdΔ¡ÑÃí+H6(* QuickDraw calls made between the PostScriptBegin *)°dONLNdÀÑ÷í*
  5511. 6(* and PostScriptEnd PicComments will be ignored by *)°dONLNd:’чB*
  5512. &(* devices that support PostScript. *)°dONLNddÈÑÙ∫*>PicComment(PostScriptHandle,GetHandleSize(PSHandle),PSHandle);°dONLNd¶˝`($~ PicComment(PostScriptEnd,0,nil);°dONLNdÀ`á*;(* Kill off the Handle we created and close the picture. *)°dONLNd&(B6 °dONLNd
  5513. `&”)HDisposHandle(PSHandle);°dONLNd%%`0¶*
  5514. ClosePicture; °dONLNd6/<:¥(VZEND; (* CreatePicture *)
  5515. °dONLNdOEQ⁄(m6%See the LaserWriter Reference Manual °dONLNdtE⁄Q⁄)¬/for more information about PicComments. See the°dONLNd§R^€(z6$PostScript Language Reference Manual°dONLNd»R€^P)√ for more information °dONLNdfiRP^Ü)u
  5516. about the °dONLNdËQÜ]⁄)6 currentpoint°dONLNdı^jC(Ü6    operator. ¡4¡˘
  5517. *P2) of 3(÷U'PR 23 - Position-Independent PostScript++M.PR.PositionIndependentPSˇh◊#ˇ ˇˇˇˇ#◊ 
  5518. IR,Times
  5519. .+Z-Developer Support Center(-Ï
  5520. March 1988 /X/
  5521. °dONLNd<)ê(EZThere are some °dONLNdê)˛)TFimportant guidelines to follow when sending PostScript directly to the°dONLNdV)<5µ(QZHLaserWriter. See the PostScript Commands section of Technical Note #91, °dONLNdû)µ5˛(Q”for a complete°dONLNd≠5<Aœ(]Z description of these guidelines.°dONLNdŒe<q¶*0Further Reference: êXê°dONLNd·rN~R+
  5522. •°dONLNd„r`~∏)The Print Manager°dONLNdı~NäR(¶l•°dONLNd˜~`äñ)    QuickDraw°dONLNdäNñR(≤l•°dONLNdä`ñ)LaserWriter Reference Manual°dONLNd ñN¢R(æl•°dONLNd"ñ`¢)"Technical Note M.IM.PictComments —°dONLNdG¢ÑÆo+$ ,  Optimizing for the LaserWriter—PicComments°dONLNdtÆN∫R(÷l•°dONLNdvÆ`∫)$PostScript Language Reference Manual°dONLNdöÆ∫k)∫, Adobe Systems°dONLNd™∫NΔR(‚l•°dONLNd¨∫`Δ3))PostScript Language Cookbook and Tutorial°dONLNd’∫3ΔÑ)”, Adobe Systems ¡X¡
  5523. (÷Z'PR 23 - Position-Independent PostScript(÷3) of 3(ÏZM.PR.PositionIndependentPSˇ◊#ˇ ˇˇˇˇ#◊†Ç 
  5524. /ZÅ#
  5525.     0Ià:µú9"{    ˇˇˇˇˇˇˇˇ#†ƒ°d
  5526. ONLNf˛†å°d1drw2…-·_ġˇˇˇˇˇè°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˙ó@†ò,Times
  5527. .R…R…+]BNew Technical Notes†ô°ddrw2:°„†ó°d1drw2eÙġˇˇˇˇˇP°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚ÄE¿†ò
  5528. ({ïDeveloper Support†ô°ddrw2:°„†ó°d`drw2-ÔˇˇˇˇˇˇKÔ- Z  ffZ°d1drw2 ¿˙ÈˇˇˇˇˇˇK°ñ x°ddrw2:°ddrw2:$°d4drw2:0°öˇÙĆò
  5529. 0(UÔ†ô°ddrw2:°„†ó°d1drw2ÔÊ˙ˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:    °öˇ˝Ä†ò
  5530.     +&    ®†ô°ddrw2:°„†ó°d1drw2Â-¯yˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚Ä%†ò
  5531. (Z\    Macintosh†ô°ddrw2:°„†ó†ç°ddrw2D†É
  5532. IR.°dONLNdn<Å(õZPR 505 - PostScript Q&As
  5533. °dONLNdÄ<ès*Printing
  5534. °dONLNd#õ<ßt* Revised by:°dONLNd/õÑߡ)HDeveloper Support Center°dONLNdHõ±ß˛(√œSeptember 1993°dONLNdWß<≥q(œZ Written by:°dONLNdcßÑ≥ˇ)HDeveloper Support Center°dONLNd|ßæ≥˛(œ‹ October 1990°dONLNdâø<À⁄(ÁZThis Technical Note contains a °dONLNd®ø⁄À˛)û9collection of Q&As relating to a specific topic—questions°dONLNd‚À<◊†(ÛZGyou’ve sent the Developer Support Center (DSC) along with answers from °dONLNd)À†◊˛(Ûæthe DSC engineers.°dONLNd<◊<„u(ˇZ
  5535. While DSC °dONLNdF◊u„˛)9Lengineers have checked the Q&A content for accuracy, the Q&A Technical Notes°dONLNdì„<Ôq( Z don’t have °dONLNdû„qÔ˛)5Qthe editing and organization of other Technical Notes. The Q&A function is to get°dONLNdÔ<˚Ÿ(Znew technical information and °dONLNdÔŸ˚˛)ù6updates to you quickly, saving the polish for when the°dONLNdE˚<(#Z,information migrates into reference manuals.°dONLNdr<k*:Q&As are now included with Technical Notes to make access °dONLNd¨k˛(;âto technical updates easier for°dONLNdÃ<+.(GZ/you. If you have comments or suggestions about °dONLNd˚.+˛)Ú*Q&A content or distribution, please let us°dONLNd&+<7\(SZknow °dONLNd++\7˛) Iby sending an AppleLink to DEVFEEDBACK. Apple Partners may send technical°dONLNdu7<Ci(_Z9questions about Q&A content to DEVSUPPORT for resolution. nXn
  5536. °dONLNdØh<wÂ*4PostScript documentation
  5537. °dONLNd»w<ɧ* Date Written:  7/13/90°dONLNdflÉ<è•* Last reviewed:  8/1/92°dONLNdˆõ<ß*,Adobe Systems publishes three great manuals °dONLNd"õ߲)·+that can help you with PostScript commands:°dONLNdNß<≥J(œZ1PostScript Language Reference Manual, PostScript °dONLNdßJ≥™(œhLanguage Tutorial,°dONLNdëß™≥Õ)` and °dONLNdñßÕ≥˛)#
  5538. PostScript°dONLNd°≥<øn(€Z    Language °dONLNd™≥nø§)2    Cookbook.°dONLNd≥≥§ø˛)6C You can find these manuals at just about any bookstore, or you can°dONLNd˜ø<Àí(ÁZEorder them through APDA by calling (800) 282-2732 or writing them at:°dONLNd=◊<„§*Apple Computer, Inc.°dONLNdR„<Ô˘* $20525 Mariani Avenue, Mail Stop 33-G°dONLNdwÔ<˚£* Cupertino, CA 95014
  5539. °dONLNdã<"†*'1AppleTalk packets and PostScriptHandle PicComment
  5540. °dONLNdΩ"<.û* Date Written:  8/7/90°dONLNd”.<:•* Last reviewed:  8/1/92°dONLNdÍF<Rõ*What’s the optimal °dONLNd˝FõR˛)_Camount of PostScript to pass in PicComment 192 for AppleTalk packet°dONLNdAR<^u(zZ throughput?°dONLNdM^<jN* ___°dONLNdQv<Ç*'There is no one optimal size that your °dONLNdxvDz)¥3PostScriptHandle PicComment should be for AppleTalk°dONLNd¨Ç<é(™Z
  5541. packets. The °dONLNdπÇé˛)CJLaserWriter driver sends different amounts of PostScript, depending on the ¡X¡
  5542. (÷ZPR 505 - PostScript Q&As(÷ˇ1) of 10(ÏZM.PR.PostScript.Q&Asˇ°¿Ù%%DSIDICT:_cv
  5543. currentdict /bu known {bu}if
  5544. userdict /_cv known not{userdict /_cv 30 dict put}if
  5545. _cv begin
  5546. /bdf{bind def}bind def
  5547. currentscreen/cs exch def/ca exch def/cf exch def
  5548. /setcmykcolor where{/setcmykcolor get /cvcmyk exch def}{/cvcmyk{1 sub 4 1 roll 3{3 index add neg dup 0 lt{pop 0}if 3 1 roll}repeat setrgbcolor pop}bdf }ifelse
  5549. /ss{//cf //ca //cs setscreen}bdf
  5550. /stg{ss setgray}bdf
  5551. /strgb{ss setrgbcolor}bdf
  5552. /stcmyk{ss cvcmyk}bdf
  5553. /min1{dup 0 eq{pop 1}if}bdf
  5554. end
  5555. currentdict /bn known {bn}if
  5556. †ø:◊#ˇ ˇˇˇˇ#◊ 
  5557. IR,Times
  5558. .+6-Macintosh Technical Notes /4/˘
  5559. °dONLNd)p*Hamount of memory that is available. It could send as little as 1K or as °dONLNdHp)⁄(Eémuch as 4K bytes of°dONLNd\)5(Q61PostScript at one time. The driver is using four °dONLNdç)5⁄)Í+4096-byte buffers to send the data, and the°dONLNdπ5AΩ(]6Vamount of data that it sends from a particular buffer is completely memory dependent. °dONLNd5ΩA⁄(]€In the°dONLNdAM~(i6general case, it does °dONLNd,A~M⁄)fHnot send any data until a particular buffer is full. The driver does not°dONLNduMYì(u6Ncontrol the number of packets that are sent over AppleTalk. When PAP receives °dONLNd√MìY⁄(u±the PostScript,°dONLNd”Ye(Å60it packages up the PostScript and sends it down °dONLNdYe⁄)ˇ$to the LaserWriter.  In general, DTS°dONLNd(eq∂(ç6Wrecommends that applications send a PostScript handle that contains 4096 bytes of data.
  5560. °dONLNdÄâòj*'2Using PostScript to control LaserWriter serial I/O
  5561. °dONLNd≥ò§Ä* Date Written:  12/6/90°dONLNd §∞á* Last reviewed:  3/28/93°dONLNd‚º»r*Where can I find °dONLNdÛºr»⁄)ZGinformation on using PostScript to control a multi-tray sheet feeder by°dONLNd;»‘ (62communicating through the LaserWriter serial port?°dONLNdn‘‡** ___°dONLNdrϯÈ*(You need to talk with Adobe on how they °dONLNdöÏȯ⁄)—1control the serial chip with PostScript. They use°dONLNdï( 62some undocumented PostScript calls to control the °dONLNd˛¯⁄)¯*serial chip on the controller board of the°dONLNd)≈(,6$LaserWriter. They can be reached at:°dONLNdN(ã*     Adobe Systems, Inc.°dONLNdg(4ë*      1585 Charleston Road°dONLNdÅ4@Æ*      Mountain View, CA   94039°dONLNd†LX"*or°dONLNd£dp *2     AppleLink Address:  ADOBE.SUPT (Tech Support)°dONLNd÷|àX*Details about °dONLNd‰|Xà⁄)@Qinstalling feeder resources for Macintosh into the LaserWriter driver 7.0 dialogs°dONLNd6àîC(∞6>are available in the Macintosh Technical Note “Feeder Fodder.”
  5562. °dONLNdu¨ª*'$How to inhibit LaserWriter test page
  5563. °dONLNdöª«Ü* Date Written:  12/24/90°dONLNd≤«”Å* Last reviewed:  8/1/92°dONLNd…flÎ˚*0How do I inhibit the test page on a LaserWriter?°dONLNd˙Θ** ___°dONLNd˛T*F1. Use the LaserWriter Utility to turn the startup page off (best), or°dONLNdE'*.2. Download the following PostScript commands:,
  5564. Courier
  5565.     °dONLNdt3>©*serverdict begin 0 exitserver°dONLNdí=Hh*
  5566. statusdict begin°dONLNd£GR|*
  5567. false setdostartpage°dONLNd∏Q\'*
  5568. end
  5569. °dONLNdºgsΔ*UThe above commands can be downloaded from your Macintosh to the printer several ways:°dONLNdã∫*V1. Use the menu command in the LaserWriter Utility that comes with System 7 (easiest).°dONLNdiãóå* N2. You can use a PostScript utility like LaserTalk from Emerald City Software. ¡4¡˘
  5570. *#2) of 10(÷âPR 505 - PostScript Q&As+ M.PR.PostScript.Q&AsˇÄ◊#ˇ ˇˇˇˇ#◊ 
  5571. IR,Times
  5572. .+Z-Developer Support Center(-€September 1993 /X/
  5573. °dONLNd<)B(EZ63. The PostScript Language facility in Microsoft Word.°dONLNd7)<5®* 4. PSDump or PSsend°dONLNdK5<A±* R5. Use the PostScript utilities in the Developer CD’s PostScript Utilities folder.°dONLNdûA<M|* A6. Use the methods described in the Macintosh Technical Note #91.°dONLNd‡Y<er*    When you °dONLNdÈYre˛)6Lissue the commands, your LaserWriter will probably crank and grind for a few°dONLNd6e<q~(çZ?seconds (it has to re-program the EPROM inside) then after the °dONLNdue~q˛(çúlights stop flashing, your°dONLNdêq<}¿(ôZLaserWriter will no longer °dONLNd´q¿}˛)ÑBspit out the startup page until you enable the setdostartpage flag°dONLNdÓ}<â9(•Z6again (in other words, this isn’t a permanent change).°dONLNd%ï<°‰*"For more information on the above °dONLNdGh)®subject we recommend the °dONLNd`ïh°˛)ÑPostScript Language Reference°dONLNd~°<≠_(…ZManual°dONLNdѰ_≠ø)# by Adobe Systems.
  5574. °dONLNdó≈<‘Û(Z?Where to find Encapsulated PostScript file (EPSF) documentation
  5575. °dONLNd◊‘<‡û* Date Written:  4/5/91°dONLNḋ<Ï•* Last reviewed:  8/1/92°dONLNd¯<P*I’m °dONLNd¯P˛)Xdeveloping an application that creates pictures containing both QuickDraw and PostScript°dONLNda<À(,ZM(as picComments). How do I create an encapsulated PostScript file (EPSF)? Is °dONLNdÆÀ˛(,È
  5576. the format°dONLNdπ<%(8Z2explained anywhere, and is it possible to convert °dONLNdÎ%˛)È-the QuickDraw into PostScript directly in the°dONLNd<(t(DZ application?°dONLNd&(<4N* ___°dONLNd*@<Lõ*FAdobe’s EPSF format is documented in the new (2nd) edition of Adobe’s °dONLNdp@õL˛(hπPostScript Language°dONLNdÑL<Xî(tZReference Manual°dONLNdîLîX})X) (Addison-Wesley) and in “Adobe Document °dONLNdΩL}X˛)ÈStructuring Conventions,”°dONLNd◊X<dı(ÄZYavailable from Adobe Systems. Adobe’s  references explain how to structure your comments °dONLNd0Xıd˛(Äin°dONLNd3d<pv(åZDyour PostScript file so that other applications know how to read it.°dONLNdx|<à$**You probably don’t want to try to convert °dONLNd¢|$à˛)Ë(QuickDraw to PostScript directly in your°dONLNdÀà<îñ(∞ZNapplication, although it is possible. Basically, it involves translating each °dONLNdàñî˛(∞¥QuickDraw command°dONLNd+î<†¥(ºZinto PostScript, which is °dONLNdE˛)xBwhat the LaserWriter Driver does. It’s a lot of work and makes you°dONLNdà†<¨
  5577. (»Z*dependent on the QuickDraw features being °dONLNd≤†
  5578. ¨˛)—.used, which can be a problem when new features°dONLNd·¨<∏m(‘Z
  5579. are added.
  5580. °dONLNdÏ–<fl∑*'9PostScript setprintername doesn’t accept colons in string
  5581. °dONLNd&fl<Χ* Date Written:  4/16/91°dONLNd=Î<˜•* Last reviewed:  8/1/92°dONLNdT<¬*MWhy can’t I use a colon with the PostScript command setprintername to change °dONLNd°¬˛(+‡ the Personal°dONLNdÆ<¨(7ZKLaserWriter NT network name and type, but it works with the LaserWriter II?°dONLNd˙<'N* ___°dONLNd˛3<?ƒ*The reason that the Personal °dONLNd3ƒ?˛)à@LaserWriter NT is not accepting the PostScript you’re sending is°dONLNd\?<K‰(gZ#not because of a bug, but rather a °dONLNd?‰K˛)®8bug fix. Colons have never been acceptable in the string°dONLNd∏K<Wœ(sZpassed to setprintername. (See °dONLNd◊KœW9)ìpage 296 of Adobe’s °dONLNdÎK9W˛)j&PostScript Language Reference Manual.)°dONLNd    W<cª(ZQThe reason the call works in older LaserWriters but not the Personal LaserWriter °dONLNd    cWªc˛(ŸNT is that the°dONLNd    rc<oQ(ãZNT °dONLNd    ucQo˛)Thas a newer version of PostScript in it. Older versions of PostScript didn’t enforce°dONLNd     o<{ı(óZWAdobe’s printer naming conventions. The setprintername restrictions have been enforced °dONLNd
  5582. !oı{˛(óin°dONLNd
  5583. ${<áx(£ZAmore recent versions, however. Therefore, colons are not allowed. ¡X¡
  5584. *3PR 505 - PostScript Q&As(÷ˇ3) of 10(ÏZM.PR.PostScript.Q&Asˇ‘◊#ˇ ˇˇˇˇ#◊ 
  5585. IR,Times
  5586. .+6-Macintosh Technical Notes /4/˘
  5587. °dONLNd)H*>If you need to change the LaserWriter network type, it can be °dONLNd>H)⁄(Efdone with the AppleTalk-type°dONLNd[)5à(Q6parameter described on °dONLNdr)à5Ô)ppage 105 of Apple’s °dONLNdÜ)Ô5Z)gLaserWriter Reference°dONLNdõ)Z5⁄)k manual. This method will°dONLNdµ5AÁ(]6,work on the new printers as well as the old.
  5588. °dONLNd‚Yh3*'(PostScript code for renaming LaserWriter
  5589. °dONLNd htz* Date Written:  6/5/91°dONLNd!tÄÅ* Last reviewed:  8/1/92°dONLNd8åòˇ*-In checking a printer name to ensure an even °dONLNdeåˇò⁄)Á*number of characters, does the LaserWriter°dONLNdêò§
  5590. (¿64Namer append a space to the end if the total is odd?°dONLNd≈§∞** ___°dONLNd…º»„**In a nutshell, yes. The Namer does indeed °dONLNdÛº„»⁄)À2append an extra space to odd-length printer names.°dONLNd&»‘•(6The reasoning behind this is °dONLNdC»•‘⁄)ç;to be compatible with some of the old 68000 processors. The°dONLNd‘‡®(¸6addressing scheme of these °dONLNdö‘®‡÷)ê7old processors requires that memory be accessed by even°dONLNd—‘÷‡⁄(¸Ù-°dONLNd“‡Ï=(68numbered addresses. To get at a piece of memory located °dONLNd
  5591. ‡=Ï⁄([after an odd-length LaserWriter°dONLNd*ϯn(6name, you would °dONLNd:Ïn¯⁄)VJneed to get an odd-numbered address (which is not directly possible). This°dONLNdÖ¯ƒ( 6 obviously can be worked around, °dONLNd•¯ƒ⁄)¨7but the authors of the Namer felt it best to avoid this°dONLNd›Æ(,6altogether by padding the name °dONLNd¸Æ⁄)ñ<when necessary. It’s worth noting that the version 7.0 Namer°dONLNd9X(86does this too.°dONLNdH(4´*WIf you’d like to work around this, here’s an alternate method for renaming the printer:°dONLNd†@Lz*The printer name is °dONLNd¥@zL⁄)bIstored as a string in the persistent parameters of all LaserWriters. This°dONLNd˛LX1(t6:string can be changed by the following PostScript program:,
  5592. Courier
  5593.     °dONLNd9doΩ*!    serverdict begin 0 exitserver°dONLNd[ny˘*
  5594. -    statusdict begin (NEWNAME) setprintername
  5595. °dONLNdâÑêg*<Replace NEWNAME with the name you want for the printer. The °dONLNd≈Ñgê⁄(¨Öname can be up to 31°dONLNd⁄êúJ(∏6 characters °dONLNdÂêJú⁄)2Sand should consist entirely of printing characters--the “@” and “:” cannot be used.°dONLNd9ú®º(ƒ6#Note that parentheses are required.°dONLNd]¥¿F*>This program can be downloaded to the LaserWriter in batch or °dONLNdõ¥F¿⁄(‹d interactive mode. In interactive°dONLNdº¿ÃÑ(Ë6mode you should type °dONLNd—¿ÑÃ⁄)lDboth command strings on the same line before pressing Enter, because°dONLNdÃÿÕ(Ù6$exitserver disconnects you from the °dONLNd:ÃÕÿ⁄)µ4printer. When you reestablish your connection to the°dONLNdoÿ‰π(6"printer, the name will be changed.°dONLNdí¸›*(Make sure you have selected the correct °dONLNd∫›¸⁄)≈0LaserWriter using the Chooser before downloading°dONLNdθ.($68this program, so you don’t rename the wrong LaserWriter.
  5596. °dONLNd$ /ë*'7Printing 2-byte bitmap fonts on PostScript LaserWriters
  5597. °dONLNd\/;Ä* Date Written:  9/29/91°dONLNds;GÅ* Last reviewed:  8/1/92°dONLNdäS_Ò*+The Macintosh Technical Note #91 refers to °dONLNdµSÒ_⁄)Ÿ,using QuickDraw picComments to print rotated°dONLNd‚_k0(á6text, °dONLNdË_0k⁄)Ubut this doesn’t work for 2-byte Japanese text. Is there a recommended workaround for°dONLNd    >kwX(ì6
  5598. this problem?°dONLNd    LwÉ** ___ ¡4¡˘
  5599. *74) of 10(÷âPR 505 - PostScript Q&As+ M.PR.PostScript.Q&Asˇ6◊#ˇ ˇˇˇˇ#◊ 
  5600. IR,Times
  5601. .+Z-Developer Support Center(-€September 1993 /X/
  5602. °dONLNd<)ß(EZTwo-byte characters °dONLNdß)˛)k=don’t print when using the TextBegin, TextCenter, and TextEnd°dONLNdR)<5≤(QZKPicComments because of the structure of the data that is being sent in the °dONLNdù)≤5˛(Q–
  5603. comments. The°dONLNd´5<Ac(]Z>LaserWriter driver uses these PicComments to rotate text, and °dONLNdÈ5cA˛(]Å"it is not expecting the data to be°dONLNd A<Mà(iZGin the 2-byte format. The 2-byte format is converted to bitmap data by °dONLNdSAàM˛(i¶the driver, so the data is°dONLNdnM<Y¯(uZ^ignored and nothing is printed. The driver is expecting the comments to contain “normal” text.°dONLNdÕe<qÄ*Since the data °dONLNd‹eÄq˛)DJis in bitmap format, you can use the RotateBegin and RotateEnd PicComments°dONLNd'q<}·(ôZ$to perform the rotation, as follows:,
  5604. Courier
  5605.     °dONLNdLâ<îs* RotateBegin°dONLNdXì<ûã*
  5606. C    DrawString (...);  << To rotate your 2 byte Japanese characters°dONLNdúù<®i*
  5607.     RotateEnd
  5608. °dONLNd¶≥<øÍ*(The tricky part of the solution is that °dONLNdŒ≥Íø˛)Æ7you only need to use this approach when you’re printing°dONLNdø<À&(ÁZ02-byte Japanese bitmap fonts. Therefore, you’ll °dONLNd6ø&À˛)Í,need to check the type of data that is to be°dONLNdcÀ<◊ (ÛZ.printed, and send the appropriate PicComments.°dONLNdí„<Ô‡*PYou can also use the following PicComments to hide the QuickDraw representation °dONLNd‚„‡Ô˛( ˛of the°dONLNdÈÔ<˚«(Zrotated text, as shown below:
  5609.     °dONLNd<á*PostScriptBegin°dONLNd<;*
  5610. 3    CopyBits (...);   << For the QuickDraw printers°dONLNdK<&}*
  5611.  
  5612. PostScriptEnd
  5613. °dONLNdY1<=Á*VThe PostScriptBegin and PostScriptEnd PicComments are used to hide the CopyBits calls °dONLNdØ1Á=˛(Yfrom°dONLNd¥=<I∑(eZthe LaserWriter driver in °dONLNdŒ=∑I˛){>a device-independent manner. When you use PostScriptBegin, the°dONLNd
  5614. I<U•(qZHLaserWriter driver doesn’t interpret any QuickDraw calls until it finds °dONLNdUI•U˛(q√the PostScriptEnd°dONLNdgU<a7(}Z/PicComment. Since QuickDraw printer drivers do °dONLNdñU7aF)˚not°dONLNdôUFa˛)# understand the PostScriptBegin and°dONLNdΩa<mÉ(âZPostScriptEnd °dONLNdÀaÉm˛)GJPicComments, they ignore the PicComments, and the CopyBits call is used to°dONLNdm<yÿ(ïZ"perform the rotation of your text.°dONLNd9Ö<ë≈*There is one problem with °dONLNdSÖ≈ë˛)â=the previously mentioned solution: If you record the previous°dONLNdëë<ùÃ(πZTPicComments into a picture and print it, everything will print exactly as expected, °dONLNdÂëÃù˛(πÍ
  5615. but if you°dONLNdù<©"(≈Z2display the picture into a window, you’ll see the °dONLNd"ù"©N)Ê    unrotated°dONLNd+ùN©≠), version of the text. °dONLNdAù≠©˛)_This is definitely°dONLNdT©<µW(—Z=a bug, which has been reported, but it won’t be fixed in the °dONLNdë©Wµ˛(—u!very near future. So, what do you°dONLNd≥µ<¡J(›Z7do in the meantime? You have the following two options:°dONLNdÎÕ<Ÿ`*A1) Do not export pictures that contain this type of rotated data.°dONLNd-Ÿ<Â∞* O2) Export the picture with this problem, and explain the problem to your users.°dONLNd}Ò<˝≥*Neither solution is ideal. °dONLNdòÒ≥˝˛)wDQuite a few applications out in the market today have decided to use°dONLNd›˝<    b(%Zidea #2.
  5616. °dONLNdÊ!<0É*'/Macintosh spooling should be device independent
  5617. °dONLNd    0<<û* Date Written:  1/1/90°dONLNd    ,<<H•* Last reviewed:  8/1/92°dONLNd    CT<`É*EHow can I tell whether the chosen printer supports PostScript or not?°dONLNd    â`<lN* ___°dONLNd    çx<Ñt*<There is no supported method for determining whether or not °dONLNd    …xtÑ˛(†ía device speaks PostScript.°dONLNd    ÂÑ<ê$(¨Z+Apple engineering would like all Macintosh °dONLNd
  5618. Ñ$ê˛)Ë)applications to spool both PostScript and ¡X¡
  5619. (÷ZPR 505 - PostScript Q&As(÷ˇ5) of 10(ÏZM.PR.PostScript.Q&AsˇΔ◊#ˇ ˇˇˇˇ#◊ 
  5620. IR,Times
  5621. .+6-Macintosh Technical Notes /4/˘
  5622. °dONLNd)*4QuickDraw regardless of the chosen printer, so that °dONLNd4)⁄)˛(the spool file is device-independent and°dONLNd])5>(Q6@can be redirected after spooling. Since engineering is strongly °dONLNdù)>5⁄(Q\encouraging developers to spool°dONLNdΩ5Aò(]6both models, it is doubtful °dONLNdŸ5òA⁄)ÄAthat Apple will be providing a query mechanism in the future. The°dONLNdAMw(i6best method is to °dONLNd-AwM⁄)_Aassume PostScript is available, and format your document based on°dONLNdoMY(u67information returned by PrGeneral and the print record.
  5623. °dONLNdßqÄB*'*LaserWriter driver and PostScript showpage
  5624. °dONLNd“Äåz* Date Written:  1/1/90°dONLNdËåòá* Last reviewed:  6/14/93°dONLNd§∞ü*SWhen I print a PostScript file, why do I get one blank page for every page printed?°dONLNdT∞º** ___°dONLNdX»‘ö*RYour PostScript file probably contains calls to the PostScript showpage operator. °dONLNd™»ö‘⁄(∏
  5625. This operator°dONLNd∏‘‡9(¸6is also °dONLNd¿‘9‡⁄)!Ucalled by the Macintosh LaserWriter driver when it receives the PrClosePage call. The°dONLNd‡Ïæ(6Zsolution to this problem is to strip showpage calls from the file before sending the file °dONLNdp‡æÏ⁄(‹to the°dONLNdwϯê(6MLaserWriter. If you send one QuickDraw graphic at the beginning of each page,,
  5626. Courier
  5627.     °dONLNd≈ü*    MoveTo(-32000, -32000);°dONLNd·c*
  5628.     Line(0, 0);
  5629. °dONLNdÒ$0Ë*+the LaserWriter driver will handle calling °dONLNd$Ë0⁄)–-showpage for you. Versions of the LaserWriter°dONLNdJ0<u(X6Gdriver before 5.2 do not send the showpage operator unless a QuickDraw °dONLNdë0u<⁄(Xìdrawing routine (that°dONLNdß<He(d6is, something °dONLNdµ<eH⁄)M>other than PicComment) is sent. This is why you need to do the°dONLNdÙHTõ(p6FMoveTo/LineTo. Versions 5.2 and later will send the showpage operator °dONLNd:HõT⁄(pπ whether any°dONLNdFT`Ã(|6VQuickDraw has been sent or not. Since you can’t be sure whether showpage will be sent °dONLNdúTÃ`⁄(|Ífor°dONLNd†`lS(à6Gyou or not, the best solution is to let the LaserWriter driver send it.
  5630. °dONLNdËÑìÉ*'3PicComment TextIsPostScript versus PostScriptHandle
  5631. °dONLNdìüz* Date Written:  1/1/90°dONLNd2ü´á* Last reviewed:  6/14/93°dONLNdJ∑√°*When using the Macintosh °dONLNdc∑°√⁄)â<TextIsPostScript picture comment, my PostScript code is also°dONLNd†√œ (Î63“printed” on the ImageWriter. Why isn’t it ignored?°dONLNd‘œ€** ___°dONLNdÿÁÛÌ*'One of the comments, TextIsPostScript, °dONLNdˇÁÌÛ⁄)’+allows the application to use the QuickDraw°dONLNd+ÛˇT(6ADrawString procedure to send the PostScript code. This method is °dONLNdlÛTˇ⁄(rno longer recommended, as°dONLNdܡ ø('6%it is not device independent. If you °dONLNd´ˇø ÷)ß7use the TextIsPostScript comment when printing to a non°dONLNd‚ˇ÷ ⁄('Ù-°dONLNd„ ,(36:PostScript device, the PostScript code will be printed as °dONLNd ,⁄(3J#text. On an ImageWriter, the entire°dONLNdA#»(?6#PostScript program will be printed °dONLNdd»#⁄)∞5as one line on the page, because the TextIsPostScript°dONLNdö#/ù(K6KPicComment is ignored by the ImageWriter drivers, and the DrawString calls °dONLNdÂ#ù/⁄(Kª are executed°dONLNdÚ/;F(W6    normally.°dONLNd¸GSØ*PTo avoid this problem, developers should use the PostScriptHandle comment. This °dONLNd    LGØS⁄(oÕcomment°dONLNd    TS_x({6accepts a handle as °dONLNd    hSx_⁄)`Fa parameter. The handle points to the PostScript code that you want to°dONLNd    Ø_k    (á61download. This comment is better for two reasons:°dONLNd    ·wÉU*
  5632. First, there °dONLNd    ÓwUÉ⁄)=Jis no QuickDraw/PostScript interaction. For example, early versions of the°dONLNd
  5633. 9Éèfl(´6+LaserWriter driver sent the strings passed °dONLNd
  5634. dÉflè⁄)«5to DrawString as-is. The latest version of the driver ¡4¡˘
  5635. (÷66) of 10(÷âPR 505 - PostScript Q&As+ M.PR.PostScript.Q&Asˇ◊#ˇ ˇˇˇˇ#◊ 
  5636. IR,Times
  5637. .+Z-Developer Support Center(-€September 1993 /X/
  5638. °dONLNd<)Œ(EZappends carriage returns onto °dONLNdŒ)˛)í>those strings. If your application is expecting the DrawString°dONLNd])<5T(QZ;calls to work one way or another, you might get a surprise.°dONLNdôA<MS*The °dONLNdùASM˛)Qother reason for using the PostScriptHandle comment involves device independence.°dONLNdÔM<Y≠(uZWhen a non-PostScript °dONLNdM≠Y˛)qDdriver sees the PostScriptHandle PicComment, it not only ignores the°dONLNdJY<eô(ÅZcomment, but also °dONLNd\Yôe˛)]Fignores the PostScript data that was passed to the comment, so nothing°dONLNd£e<q¢(çZJprints if you use the PostScriptHandle comment on a non-PostScript driver.°dONLNdÓ}<â]*X-Ref:°dONLNdıâ<ï…* LMacintosh Technical Note  “How To Produce Continuous Sound Without Clicking”
  5639. °dONLNdB≠<ºfl*'<How to send PostScript from the Macintosh to the LaserWriter
  5640. °dONLNdº<»û* Date Written:  5/3/89°dONLNdï»<‘´* Last reviewed:  6/14/93°dONLNd≠‡<Ïs*?How do I send PostScript from the Macintosh to the LaserWriter?°dONLNdÌÏ<¯N* ___°dONLNdÒ<|*DThe best method for sending PostScript to the LaserWriter is to use °dONLNd5|˛(,öthe PostScriptHandle (kind°dONLNdP<Á(8Z= 192) PicComment documented °dONLNdmÁ˛)´4in the Macintosh Technical Notes “Optimizing for the°dONLNd¢<((DZ'LaserWriter” and “Picture Comments—the °dONLNd…(˛)’+Real Deal.” There are a few PicComments for°dONLNdı(<4 (PZOsending PostScript to the LaserWriter, but the easiest to use and most problem °dONLNdD( 4˛(PË free is the°dONLNdP4<@(\Z'PostScriptHandle comment. One model is:,
  5641. Courier
  5642.     °dONLNdxL<Wå* PrOpenPage(...)°dONLNdâV<am*
  5643. = { Send some QuickDraw so that the Printing Manager gets a  }°dONLNd«`<k6*
  5644. 2 { chance to define the clip region.             }°dONLNd˙j<u¥*
  5645.  MoveTo(-32000, -32000);°dONLNdt<x*
  5646.  Line(0, 0);°dONLNd à<ìı*% PicComment(PostScriptBegin, 0, NIL);°dONLNdFú<ß    *) { QuickDraw representation of graphic. }°dONLNdp¶<±ñ*
  5647.  MoveTo(100, 100);°dONLNdÉ∞<ªñ*
  5648.  LineTo(200, 200);°dONLNdñƒ<œ** { PostScript representation of graphic. }°dONLNd¡Œ<ŸY*
  5649. 9 thePSHandle^^ := '100 100 moveto 200 200 lineto stroke';°dONLNd˚ÿ<„ï*
  5650. E PicComment(PostScriptHandle,GetHandleSize(thePSHandle),thePSHandle);°dONLNdAÏ<˜Î*# PicComment(PostScriptEnd, 0, NIL);°dONLNdeˆ<ë*
  5651.  PrClosePage(...)
  5652. °dONLNdw <¥*The described fragment °dONLNdé ¥˛)xBprints a line on any type of printer, PostScript or not. The first°dONLNd—<$˘(@Z$MoveTo/Line combination is required °dONLNdı˘$˛)Ω3to give the LaserWriter driver a chance to define a°dONLNd)$<0⁄(LZ!clipping region. The LaserWriter °dONLNdJ$⁄0˛)û=driver replaces the grafProcs record in the GrafPort returned°dONLNdà0<<°(XZKfrom PrOpenDoc. In order for the LaserWriter driver to get execution time, °dONLNd”0°<˛(Xøyou must execute a°dONLNdÊ<<H™(dZIQuickDraw drawing routine that calls one of the grafProcs. In this case, °dONLNd/<™H˛(d»the MoveTo/Line°dONLNd?H<Tz(pZ combination °dONLNdKHzT˛)>Ois sent firing the StdLine grafProc. When StdLine executes, it notices that the°dONLNdõT<`Ê(|Z]GrafPort has been reinitialized, and therefore initializes the clipping region for the port. °dONLNd¯TÊ`˛(|Until°dONLNd˛`<l¬(àZTthe MoveTo/Line combination is executed, the clipping region for the port is set to °dONLNd    R`¬l˛(à‡
  5653. (0,0,0,0). If°dONLNd    `l<x≥(îZMPostScript code is sent via the PostScriptHandle PicComment before executing °dONLNd    ≠l≥x˛(î—
  5654. any QuickDraw°dONLNd    ªx<Ñ≠(†ZQroutines, all PostScript operations will be clipped to (0,0,0,0). The next thing °dONLNd
  5655. x≠Ñ˛(†Àto do is send the°dONLNd
  5656. Ñ<ê!(¨Z,PostScriptBegin PicComment. This comment is °dONLNd
  5657. JÑ!ê˛)Â.recognized only by PostScript printer drivers. ¡X¡
  5658. (÷ZPR 505 - PostScript Q&As(÷ˇ7) of 10(ÏZM.PR.PostScript.Q&AsˇÆ◊#ˇ ˇˇˇˇ#◊ 
  5659. IR,Times
  5660. .+6-Macintosh Technical Notes /4/˘
  5661. °dONLNd)7*When °dONLNd7)⁄)Ythe driver receives this comment, it saves the current state of the PostScript device (by°dONLNd_)5+(Q68executing the PostScript gsave operator), then disables °dONLNdó)+5⁄(QI!all QuickDraw drawing operations.°dONLNdπ5A!(]66This way, the QuickDraw representation of the Graphic °dONLNdÔ5!A⁄(]?&will be ignored by PostScript devices.°dONLNdAMê(i6In the previous example, °dONLNd/AêM⁄)x@the MoveTo/LineTo combination is only executed on non-PostScript°dONLNdpMYß(u6devices. The next comment is °dONLNdçMßY⁄)è?the PostScriptHandle PicComment. This tells the driver that the°dONLNdÕYe∂(Å6"data in thePSHandle is to be sent °dONLNdÔY∂e⁄)û=to the device as PostScript code. The driver then passes this°dONLNd-eqg(ç6code unchanged °dONLNd<egq⁄)OJto the PostScript device for execution. The PostScriptHandle PicComment is°dONLNdáq}¥(ô6Sonly recognized by PostScript printer drivers. The last PicComment, PostScriptEnd, °dONLNd⁄q¥}⁄(ô“    tells the°dONLNd‰}âf(•6driver to restore °dONLNdˆ}fâ⁄)NPthe previous state of the device (via a PostScript grestore call), and to enable°dONLNdGâï‘(±6$QuickDraw drawing operations. Since °dONLNdkâ‘ï⁄)º1all PicComments are ignored by QuickDraw devices,°dONLNdùï°(Ω64only the QuickDraw representation is printed. Since °dONLNd—ï°⁄)˜+PostScriptBegin tells PostScript drivers to°dONLNd˝°≠ñ(…6Kignore QuickDraw operations, only the PostScript representation is printed °dONLNdH°ñ≠⁄(…¥
  5662. on PostScript°dONLNdV≠π¸(’6,devices. This is a truly device-independent °dONLNdÇ≠¸π⁄)‰(method for providing both PostScript and°dONLNd´π≈‚(·6(QuickDraw representations of a document.
  5663. °dONLNd‘›Ï}*'5Converting PostScript file to Encapsulated PostScript
  5664. °dONLNd
  5665. ϯÄ* Date Written:  5/19/92°dONLNd!¯á* Last reviewed:  6/14/93°dONLNd9C*9What needs to be added to an ordinary PostScript file to °dONLNdrC⁄(8aconvert it to an Encapsulated°dONLNdê(Ä(D6PostScript (EPS) file?°dONLNdß(4** ___°dONLNd´@L*1The latest Adobe “red book,” PostScript Language °dONLNd‹@L⁄)˘'Reference Manual (2nd Edition), has the°dONLNdLXÆ(t6Rinformation you need. Appendix H: Encapsulated PostScript File Format Version 3.0 °dONLNdVLÆX⁄(tà   describes°dONLNd`Xd[(Ä6>the contents of an EPS file. Appendix G: Document Structuring °dONLNdûX[d⁄(ÄyConventions specifies the°dONLNd∏dpé(å6Msingle-page document PS file, which must include at least these two comments:,
  5666. Courier
  5667.     °dONLNd|áü*    %!PS-Adobe-3.0 EPSF-3.0°dONLNd"Üë¬*
  5668. "    %%BoundingBox: llx lly urx ury
  5669. °dONLNdEú®X*BYou might find the following references from Adobe useful as well:°dONLNdॿœ*X    Adobe Illustrator Document Format Specification v2.0 (Adobe Technical Note #LPS5007)°dONLNd·¿Ãs* F    Encapsulated PostScript Files v1.2 (Adobe Technical Note #LPS5002)°dONLNd(ÿ‰ã*You can reach Adobe at:°dONLNd@¸ï*    Corporate Headquarters°dONLNd[¸÷* %    1585 Charleston Road, PO Box 7900°dONLNdÅ¡*      Mountain View, CA 94039-7900°dONLNd¢ À* $    (415) 961-4111 Developer Support°dONLNd«,8Ç*Macintosh Technical °dONLNd€,Ç8⁄)j=Note “Picture Comments—The Real Deal” (formerly #91) contains°dONLNd    8D<(`6<sample code for using all of the supported Picture Comments.
  5670. °dONLNd    V\kA*'+Printing halftone images on the LaserWriter
  5671. °dONLNd    Çkwz* Date Written:  5/3/89°dONLNd    òwÉÅ* Last reviewed:  8/1/92 ¡4¡˘
  5672. *78) of 10(÷âPR 505 - PostScript Q&As+ M.PR.PostScript.Q&Asˇ\◊#ˇ ˇˇˇˇ#◊ 
  5673. IR,Times
  5674. .+Z-Developer Support Center(-€September 1993 /X/
  5675. °dONLNd<)›(EZ How can I print halftone images °dONLNd ›)˛)°7on the LaserWriter? How do I use the PostScript “image”°dONLNdX)<5œ(QZ operator for printing halftones?°dONLNdy5<AN* ___°dONLNd}M<Y`*<The PostScript “image” operator is similar to the Macintosh °dONLNdπM`Y˛(u~QuickDraw CopyBits routine. It°dONLNdÿY<eQ(ÅZcan °dONLNd‹YQe˛)Pbe used by converting a QuickDraw bitmap/pixmap into an image call. This is only°dONLNd-e<qy(çZ
  5676. necessary if °dONLNd:eyq˛)=Pyou are printing color information with a PostScript printer driver that doesn’t°dONLNdãq<}Å(ôZsupport Color °dONLNdôqÅ}˛)EHQuickDraw. LaserWriter drivers up to 5.2 do NOT support Color QuickDraw.°dONLNd‚}<âW(•Z<If you want to send color information to a LaserWriter with °dONLNd}Wâ˛(•u#version 5.2 of the driver, you will°dONLNdBâ<ïı(±ZYhave to convert your color images into image commands. Before doing this it is important °dONLNdõâıï˛(±to°dONLNdûï<°o(ΩZ
  5677. check the °dONLNd®ïo°˛)3KGrafPort returned by PrOpenDoc. If this port is a Color QuickDraw port (for°dONLNdÙ°<≠ï(…ZDexample, portBits.rowBytes < 0) then you should use Color QuickDraw °dONLNd8°ï≠˛(…≥commands and let the°dONLNdM≠<π(’Z+driver handle the conversion to PostScript.°dONLNdy≈<—‡*NAbout image: The PostScript image operator is used to send bitmaps or pixmaps °dONLNd«≈‡—˛(Ì˛to the°dONLNdŒ—<››(˘ZXLaserWriter. The image operator can handle depths from one to eight bits per pixel. Our °dONLNd&—››˛(˘˚current°dONLNd.›<Èw(Z=LaserWriters can image only about 16 shades of gray, but the °dONLNdk›wÈ˛(ïprinted page will look like°dONLNdáÈ<ı](Z?there’s more. Because the image operator is still a PostScript °dONLNdΔÈ]ı˛({$operator, it expects its data in the°dONLNdÎı<†(Zform of hexadecimal °dONLNdˇı†˙)dEbytes. The bytes are represented by two ASCII characters(“0”-”9,” “A”°dONLNdDı˙˛(-°dONLNdE<
  5678. ˝()Z^”F”) per byte. The image operator takes these parameters: width height depth matrix image-data°dONLNd§<%ã*?The first three are the width, height, and depth of the image, °dONLNd„ã%˛(A©and the matrix is the°dONLNd˘%<1∫(MZtransformation matrix to °dONLNd%∫1˛)~=be applied to the current matrix. See the PostScript Language°dONLNdP1<=}(YZ?Reference Manual for more information. The image data is where °dONLNdè1}=˛(Yõthe actual hex data should°dONLNd™=<I[(eZ?go. Instead of inserting the data between the first parameters °dONLNdÈ=[I˛(ey$and the image operator itself, it is°dONLNdI<U”(qZ[better to use a small PostScript procedure to read the data starting right after the image °dONLNdiI”U˛(qÒ    operator.°dONLNdsU<az(}Z For example:,
  5679. Courier
  5680.     °dONLNdÄm<x¬*N640 480 8 [640 0 0 480 0 0] {currentfile picstr readhexstring pop} image FF 00°dONLNdœw<dž*
  5681. FF 00 FF 00 FF 00...
  5682. °dONLNd‰ç<ô0*4In the preceding example, the width of the image is °dONLNdç0ô˛)Ù+640, the height is 480, and the depth is 8.°dONLNdDô<•Æ(¡ZThe matrix (enclosed in °dONLNd\ôÆ•˛)rEbrackets) is set up to draw the image starting at QuickDraw’s 0,0(top°dONLNd¢•<±â(ÕZEleft of page), and with no scaling. The PostScript code (enclosed in °dONLNdÁ•Ⱳ(Õßbraces) is not executed.°dONLNd    ±<Ωt(ŸZDInstead, it is passed to the image operator, and the image operator °dONLNd    D±tΩ˛(Ÿí calls it repeatedly until it has°dONLNd    eΩ<…Æ(ÂZLenough data to draw the image. In this case, it is expecting 640*480 bytes. °dONLNd    ±ΩÆ…˛(ÂÃWhen the image°dONLNd    ¿…<’)(ÒZ4operator calls the procedure, it does the following:°dONLNd    ı·<ÌF*1.°dONLNd    ¯·NÌ≥)KPushes the current file which in this case is the stream of data coming to °dONLNd
  5683. C·≥Ì˛(    —the LaserWriter°dONLNd
  5684. SÌN˘§(lJover AppleTalk. This is the first parameter to the readhexstring operator.°dONLNd
  5685. û<F(-Z2.°dONLNd
  5686. °NW)6Pushes picstr. picstr is a string variable defined to °dONLNd
  5687. ◊W˛(-uhold one row of hex data. The°dONLNd
  5688. ıNÂ(9l#PostScript to create the picstr is:
  5689.     °dONLNd )N4ô*/picstr 640 def
  5690. °dONLNd *?<KF(gZ3.°dONLNd -?NKú)readhexstring is °dONLNd >?úK˛)NNcalled to fill picstr with data from the current file. It begins reading bytes°dONLNd çKNWN(sl6which are the characters following the image operator.°dONLNd ƒc<oF(ãZ4.°dONLNd «cNo¡)Nreadhexstring leaves the string we want, and a boolean that we don’t want, on °dONLNd c¡o˛(ãfl
  5691. the stack, so°dONLNd #oN{(ól'we do one pop to kill off the boolean. °dONLNd Jo{˛)µ4Now the string is left behind for the image operator°dONLNd {Nán(£lto use. ¡X¡
  5692. (÷ZPR 505 - PostScript Q&As(÷ˇ9) of 10(ÏZM.PR.PostScript.Q&AsˇH◊#ˇ ˇˇˇˇ#◊ 
  5693. IR,Times
  5694. .+6-Macintosh Technical Notes /4/˘
  5695. °dONLNd)w*LUsing the above PostScript code you can easily print an image. Just fill in °dONLNdLw)⁄(Eïthe width height and°dONLNda)5m(Q6Gdepth, and send the hex data immediately following the PostScript code.°dONLNd©AM/*:Setting up for image: Most of the users of this technique °dONLNd„A/M⁄(iM"are going to want to print a Color°dONLNdMYd(u6?QuickDraw pixmap. Although the image command does a lot of the °dONLNdEMdY⁄(uÇwork for you, there are°dONLNd]Yeœ(Å6)still a couple of tricks for performance:°dONLNdáq}A*Assume °dONLNdéqA}⁄))Pthe maximum depth: Since the current version of the image operator has a maximum°dONLNdfl}â◊(•6)depth of eight bits/pixel, it is wise to °dONLNd}◊â⁄)ø1convert the source image to the same depth before°dONLNd:âïL(±6;imaging. You can do this very simply by using an offscreen °dONLNduâLï⁄(±jGrafPort that is set to eight°dONLNdìï°ù(Ω6Rbits/pixel, and then using CopyBits to do the depth conversion for you. This does °dONLNdÂïù°⁄(Ωª
  5696. a nice job of°dONLNdÛ°≠(…63converting lower resolution images to 8 bits/pixel.°dONLNd'π≈«*'Build a color table: An eight bit deep °dONLNdNπ«≈⁄)Ø7image can use only 256 colors. Since the image that you°dONLNdÜ≈—>(Ì6;are starting with is probably color, and the image you get °dONLNd¡≈>—⁄(Ì\will be grayscale, you need to°dONLNd‡—›Í(˘6-convert the colors in the source color table °dONLNd
  5697. —Í›⁄)“2into PostScript grayscale values. This is actually°dONLNd@›È»(6Zeasy to do using the Color Manager. First create a table that can hold 512 bytes. This is °dONLNdö›»È⁄(Êtwo°dONLNdûÈıÀ(6%bytes for each color value from 0 to °dONLNd√ÈÀı⁄)≥4255. Since PostScript wants the values in ASCII, you°dONLNd¯ıÀ(6$need two characters for each pixel. °dONLNdıÀ⁄)≥4Now loop through the colors in the color table. Call°dONLNdQ
  5698. t()6Index2Color to get °dONLNddt
  5699. ⁄)\Gthe real RGB color for that index, and then call RGB2HSL to convert the°dONLNd¨
  5700. ø(56"RGB color into a luminance value. °dONLNdŒ
  5701. ø⁄)ß9This value is expressed as a SmallFract which can then be°dONLNd%'(A6:scaled into a value from 0 to 255. This value should then °dONLNdB'%⁄(AE$be converted to ASCII, and stored at°dONLNdg%1ˇ(M60the appropriate location in the table. When you °dONLNdó%ˇ1⁄)Á+are done, you should be able to use a pixel°dONLNd√1=≥(Y6"value as an index into your table °dONLNdÂ1≥=⁄)õ=of PostScript color values. For each pixel in the image, send°dONLNd#=I∏(e6"two characters to the LaserWriter.°dONLNdFUaò*VSending the data: Once you have set up the color table, all that’s left to do is loop °dONLNdúUòa⁄(}∂through all of°dONLNd´amè(â6Othe pixels, and send their PostScript representation to the LaserWriter. There °dONLNd˙aèm⁄(â≠are a couple of°dONLNd
  5702. myà(ï6ways to do this. One is °dONLNd"mày⁄)pFto use the low-level Print Manager interface and stream the PostScript°dONLNdiyÖ–(°6%using the stdBuf PrCtlCall. Although °dONLNdéy–Ö⁄)∏7this seems like it would be the fastest way, the latest°dONLNdΔÖëQ(≠6Eversion of the LaserWriter driver (5.0) converts all low-level calls °dONLNd     ÖQë⁄(≠oto their high level equivalent°dONLNd    *ëùm(π6before executing °dONLNd    ;ëmù⁄)UIthem, so the low-level interface is no longer faster than the high level.°dONLNd    Öù©Ã(≈6TAnother way is to use the high-level Print Manager interface, and send the data via °dONLNd    Ÿùé⁄(≈Íthe°dONLNd    ›©µ¯(—6*PostScriptHandle PicComment. This enables °dONLNd
  5703. ©¯µ⁄)‡+you to buffer a large amount of data before°dONLNd
  5704. 3µ¡“(›6Zactually sending it. Using this second technique, you should be able to image a Macintosh °dONLNd
  5705. 絓¡⁄(›II°dONLNd
  5706. ê¡Õz(È6Gscreen in about 5 minutes on a LaserWriter Plus, and about 1.5 minutes °dONLNd
  5707. ◊¡zÕ⁄(Èòon a LaserWriter II°dONLNd
  5708. ÎÕŸ5(ı6NTX.°dONLNd
  5709. ÂÒ9*X-Ref:°dONLNd
  5710. ˜Ò˝÷* %PostScript Language Reference Manual,°dONLNd Ò÷˝')æ Adobe Systems. ¡4¡˘
  5711. (÷610)
  5712.  of 10(÷âPR 505 - PostScript Q&As+ M.PR.PostScript.Q&Asˇ>◊#ˇ ˇˇˇˇ#◊†Ç 
  5713. /ZÅ#
  5714.     0Ià:µú9"{    ˇˇˇˇˇˇˇˇ#†ƒ°d
  5715. ONLNf˛†å°d1drw2…-·_ġˇˇˇˇˇè°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˙ó@†ò,Times
  5716. .R…R…+]BNew Technical Notes†ô°ddrw2:°„†ó°d1drw2eÙġˇˇˇˇˇP°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚ÄE¿†ò
  5717. ({ïDeveloper Support†ô°ddrw2:°„†ó°d`drw2-ÔˇˇˇˇˇˇKÔ- Z  ffZ°d1drw2 ¿˙ÈˇˇˇˇˇˇK°ñ x°ddrw2:°ddrw2:$°d4drw2:0°öˇÙĆò
  5718. 0(UÔ†ô°ddrw2:°„†ó°d1drw2ÔÊ˙ˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:    °öˇ˝Ä†ò
  5719.     +&    ®†ô°ddrw2:°„†ó°d1drw2Â-¯yˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚Ä%†ò
  5720. (Z\    Macintosh†ô°ddrw2:°„†ó†ç°ddrw2D†É
  5721. IR.°dONLNdn<Å7(õZPR 510 - Printer Driver Q&As
  5722. °dONLNdÄ<ès*Printing
  5723. °dONLNd'õ<ßt* Revised by:°dONLNd3õÑߡ)HDeveloper Support Center°dONLNdLõ±ß˛(√œSeptember 1993°dONLNd[ß<≥q(œZ Written by:°dONLNdgßÑ≥ˇ)HDeveloper Support Center°dONLNdÄßæ≥˛(œ‹ October 1990°dONLNdçø<À⁄(ÁZThis Technical Note contains a °dONLNd¨ø⁄À˛)û9collection of Q&As relating to a specific topic—questions°dONLNdÊÀ<◊†(ÛZGyou’ve sent the Developer Support Center (DSC) along with answers from °dONLNd-À†◊˛(Ûæthe DSC engineers.°dONLNd@◊<„u(ˇZ
  5724. While DSC °dONLNdJ◊u„˛)9Lengineers have checked the Q&A content for accuracy, the Q&A Technical Notes°dONLNdó„<Ôq( Z don’t have °dONLNd¢„qÔ˛)5Qthe editing and organization of other Technical Notes. The Q&A function is to get°dONLNdÙÔ<˚Ÿ(Znew technical information and °dONLNdÔŸ˚˛)ù6updates to you quickly, saving the polish for when the°dONLNdI˚<(#Z,information migrates into reference manuals.°dONLNdv<k*:Q&As are now included with Technical Notes to make access °dONLNd∞k˛(;âto technical updates easier for°dONLNd–<+.(GZ/you. If you have comments or suggestions about °dONLNdˇ.+˛)Ú*Q&A content or distribution, please let us°dONLNd*+<7\(SZknow °dONLNd/+\7˛) Iby sending an AppleLink to DEVFEEDBACK. Apple Partners may send technical°dONLNdy7<Ci(_Z9questions about Q&A content to DEVSUPPORT for resolution.°dONLNd≥O<[·* New Q&As in this Technical Note:°dONLNd‘[<g    * +Defining default LaserWriter Pro paper tray°dONLNdg<sÔ* &Code for getting selected printer name°dONLNd's<”* !StyleWriter II driver differences°dONLNdI<ãÆ* Determining printer font ∂X∂
  5725. °dONLNdb∞<øg*4+Defining default LaserWriter Pro paper tray
  5726. °dONLNdéø<Àß* Date Written:   5/17/93°dONLNd¶À<◊®* Last reviewed: 5/19/93°dONLNdΩ„<Ôq*
  5727. How can I °dONLNd«„qÔ˙)5Pset the default paper tray on my LaserWriter Pro to something other than the 250°dONLNd„˙Ô˛( -°dONLNdÔ<˚Ä(Zsheet cassette?°dONLNd(˚<N* ___°dONLNd,<o*EThe paper tray selection in the printing job dialog is not “sticky”; °dONLNdqo˛(;çit’s not preserved from job to°dONLNdê<+¬(GZjob. In LaserWriter 7.2, the °dONLNd≠¬+˛)ÜCchoice of one of the two paper trays is stored in the print record.°dONLNdÒ+<7¥(SZLYou may be able to hack out where this is stored and define a new “default” °dONLNd=+¥7˛(S“print record by°dONLNdM7<Cœ(_ZSchanging the PREC(0) resource, but this is completely unsupported and you do so at °dONLNd†7œC˛(_Ìyour own°dONLNd©C<OR(kZrisk.°dONLNdØ[<g¨*In LaserWriter driver °dONLNd≈[¨g˛)pB8.0, the default paper trays are defined in the PostScript Printer°dONLNdg<s¡(èZQDefinition (PPD) file.  If you’re sufficiently adventurous, you can edit the PPD °dONLNdYg¡s˛(èfl
  5728. file for your°dONLNdgs<l(õZ printer to °dONLNdrsl˛)0Qchange these relationships.  LaserWriter 8.0 requires files that meet the PPD 4.0°dONLNdƒ<ãw(ßZ@specification, available from Adobe’s Developer Support program. ¡X¡
  5729. */PR 510 - Printer Driver Q&As(÷ˇ1) of 21(ÏZM.PR.PrtDvr.Q&Asˇ°¿Ù%%DSIDICT:_cv
  5730. currentdict /bu known {bu}if
  5731. userdict /_cv known not{userdict /_cv 30 dict put}if
  5732. _cv begin
  5733. /bdf{bind def}bind def
  5734. currentscreen/cs exch def/ca exch def/cf exch def
  5735. /setcmykcolor where{/setcmykcolor get /cvcmyk exch def}{/cvcmyk{1 sub 4 1 roll 3{3 index add neg dup 0 lt{pop 0}if 3 1 roll}repeat setrgbcolor pop}bdf }ifelse
  5736. /ss{//cf //ca //cs setscreen}bdf
  5737. /stg{ss setgray}bdf
  5738. /strgb{ss setrgbcolor}bdf
  5739. /stcmyk{ss cvcmyk}bdf
  5740. /min1{dup 0 eq{pop 1}if}bdf
  5741. end
  5742. currentdict /bn known {bn}if
  5743. †øn◊#ˇ ˇˇˇˇ#◊ 
  5744. IR,Times
  5745. .+6-Macintosh Technical Notes /4/˘
  5746. °dONLNd)8*'&Code for getting selected printer name
  5747. °dONLNd'8DÉ* Date Written:   3/10/93°dONLNd?DPÑ* Last reviewed: 6/24/93°dONLNdV\hÑ*MHow do I get the name of the currently selected printer, for Systems 6 and 7?°dONLNd§ht** ___°dONLNd®Äå»*%The printer driver has a resource of °dONLNdÕÄ»å⁄)∞3type PAPA, ID -8192, which contains the name of the°dONLNdåòÎ(¥6.selected printer and the network object type. °dONLNd/åÎò⁄)”1This resource is amazingly easy to get; you don’t°dONLNdaò§»(¿6Weven need to know where the printer driver resource file is located. Just call PrOpen. °dONLNd∏ò»§⁄(¿ÊThe°dONLNdº§∞⁄(Ã6)Printing Manager will open the currently °dONLNd§⁄∞⁄)¬8selected printer driver for you, and place it at the top°dONLNd∞ºë(ÿ6Gof the resource chain. Then see whether you can GetResource for 'PAPA' °dONLNde∞ëº⁄(ÿØ
  5748. ID -8192, and°dONLNdsº»Ô(‰6,viola—you have a handle to the printer name.°dONLNd†‘‡d*This will work °dONLNdØ‘d‡⁄)LCunder both System 6 and System 7. However, under QuickDraw GX, this°dONLNdÛ‡ÏÅ(6method is subject to °dONLNd‡ÅÏ⁄)iEchange. Also note that this is a read-only field; changing it doesn’t°dONLNdNϯœ(6(necessarily change the selected printer.°dONLNdwù*The printer name is the first °dONLNdïù⁄)ÖEstring, and the object type is packed right up against it. If all you°dONLNd€5(86?want is the name, then here’s a C routine that will provide it:,
  5749. Courier
  5750.     °dONLNd(3«*#OSErr GetPrinterName(Str255 prName)°dONLNd?2=*
  5751. {°dONLNdA<GÜ*
  5752.   OSErr   err = noErr;°dONLNdXFQï*
  5753.   char  **papaDataHandle;°dONLNdrZeO*   PrOpen();°dONLNd~ny˛*.  papaDataHandle = Get1Resource('PAPA',-8192);°dONLNd≠Ççã*  if(!papaDataHandle) {°dONLNd≈åóÅ*
  5754.     err = ResError();°dONLNd€ñ°J*
  5755.  
  5756.   } else {°dONLNdʆ´I*
  5757. =    BlockMove(*papaDataHandle, prName, (**papaDataHandle)+1);°dONLNd$™µ˘*
  5758. -    ReleaseResource((Handle) papaDataHandle);°dONLNdR¥ø'*
  5759.   }°dONLNdV»”T*   PrClose();°dONLNdc‹ÁY*
  5760.   return err;°dONLNdqÊÒ*
  5761. }
  5762. °dONLNdsı*&!StyleWriter II driver differences
  5763. °dONLNdï#É* Date Written:   3/17/93°dONLNd≠#/Ñ* Last reviewed: 6/24/93°dONLNdƒ;G]*AMy application won’t print to a StyleWriter II although it works °dONLNd;]G⁄(c{fine on all other printers°dONLNd GSì(o6Lincluding the original StyleWriter. Can you give me any suggestions? What’s °dONLNdlGìS⁄(o±different about°dONLNd|S_o({6the StyleWriter II?°dONLNdê_k** ___°dONLNdîwÉî*The StyleWriter II driver °dONLNdÆwîÉ⁄)|?is a member of the “GrayShare” driver family, with new features°dONLNdÓÉè”(´6'such as support for grayscale printing °dONLNdÉ”è⁄)ª5(if Color QuickDraw is available) and printer sharing ¡4¡˘
  5764. (÷62) of 21(÷|PR 510 - Printer Driver Q&As+(M.PR.PrtDvr.Q&Asˇ:◊#ˇ ˇˇˇˇ#◊ 
  5765. IR,Times
  5766. .+Z-Developer Support Center(-€September 1993 /X/
  5767. °dONLNd<)Õ(EZover the network. Its internal °dONLNdÕ)˛)ë@architecture is very different from previous printer drivers. In°dONLNd`)<5U(QZspite °dONLNdf)U5˛)Wof thorough compatibility testing, some problems have shown up since the first release.°dONLNdæ5<AI(]ZIn °dONLNd¡5IA˛)
  5768. Ymany cases, the driver revealed weaknesses in the applications themselves; for some other°dONLNdA<M¡(iZRproblems, a solution will be incorporated in the next release of the driver. Here °dONLNdmA¡M˛(ifl
  5769. are currently°dONLNd{M<Y<(uZ8identified problem areas with the StyleWriter II driver:°dONLNd¥e<q@*•°dONLNd∂eEqú)    FThe StyleWriter II driver handles memory differently. For example, if °dONLNd¸eúq˛(ç∫an application has a°dONLNdqE}ë(ôcEdereferenced handle to an unlocked block while CopyBits’ing into the °dONLNdVqë}˛(ôØprinting port, this may°dONLNdn}Eâ–(•cwork fine on all other printer °dONLNdç}–â˛)ã@drivers, but the block is likely to move with the StyleWriter II°dONLNdŒâEï(±c*driver, and the results are unpredictable.°dONLNd˘°<≠@(…Z•°dONLNd˚°E≠õ)    GThe StyleWriter II driver maintains its own A5 world internally. If an °dONLNdB°õ≠˛(…πapplication installs a°dONLNdY≠Eπ(’cNgrowZone proc and forgets to set up its own A5 in the growZone proc (ignoring °dONLNdß≠π˛(’the°dONLNd´πE≈ë(·cTechnical Note °dONLNd∫πë≈˛)LC“Register A5 Within GrowZone Functions”), the growZone proc may get°dONLNd˛≈E—…(ÌcTcalled with the StyleWriter II driver’s A5, which obviously is bad for the survival °dONLNdR≈…—˛(ÌÁ of both the°dONLNd^—E›‚(˘c#application and the printer driver.°dONLNdÇÈ<ı@(Z•°dONLNdÑÈEıZ)    The °dONLNdàÈZı˛)YStyleWriter II driver calls the pIdleProc (in the job subrecord of the print record) more°dONLNd‚ıEÔ(c"often than other printer drivers; °dONLNdıÔ˛)™3in particular, it may be called during execution of°dONLNd8E
  5770. ()c-PrOpenDoc. If an application reloads a print °dONLNde
  5771. ˛)”.record previously used, containing an old (now°dONLNdî
  5772. Efl(5cOinvalid) pointer to an idleProc, and doesn’t update the pIdleProc field before °dONLNd„
  5773. fl˛(5˝calling°dONLNdÎE%Õ(AcPrOpenDoc, disaster is very °dONLNdÕ%˛)à?likely. Note that the TechNote “pIdle Proc (or how to let users°dONLNdG%E1å(Mc know what’s °dONLNdS%å1˛)GFgoing on during print time)” recommends installing the idleProc before°dONLNdö1E=Ä(Yc
  5774. PrOpenDoc.°dONLNd•I<U@(qZ•°dONLNdßIEUÚ)    "Like most other QuickDraw printer °dONLNd…IÚU˛)≠8drivers, the StyleWriter II driver uses algorithms built°dONLNdUEaÿ(}cinto QuickDraw for rasterizing °dONLNd!Uÿa˛)ì>picture elements like ovals and arcs, but not necessarily with°dONLNd`aEm[(âc9the same sequence of coordinate transformations. Because °dONLNdôa[m˛(ây#of the 360 dpi resolution, internal°dONLNdΩmEy4(ïc.computations with the transformed coordinates °dONLNdÎm4y˛)Ô(may hit the 16-bit integer limitation of°dONLNdyEÖ€(°cQuickDraw, and reveal bugs in °dONLNd2y€Ö˛)ñ:the old QuickDraw routines that have never been discovered°dONLNdmÖEëd(≠cso far.°dONLNdvù<©@(≈Z•°dONLNdxùE©Ä)    @The StyleWriter II driver (version 1.0) contains STR# resources °dONLNd∏ùÄ©˛(≈ûwith positive ID numbers°dONLNd—©Eµß(—cLthat may conflict with STR# resources in an application. This will be fixed °dONLNd    ©ßµ˛(—≈in the next release°dONLNd    1µE¡É(›cof the driver.°dONLNd    @Õ<Ÿ@(ıZ•°dONLNd    BÕEŸï)    @Under certain circumstances, the StyleWriter II driver seems to °dONLNd    ÇÕïŸ˛(ı≥have trouble with a°dONLNd    ñŸEÂs(c@PmForeColor call. This is under investigation and will be fixed.
  5775. °dONLNd    ◊˝< „((ZDetermining printer font
  5776. °dONLNd     <ü* Date written: 1/26/93°dONLNd
  5777. <$®* Last reviewed: 4/26/93°dONLNd
  5778. 0<<v*COur application must print with Helvetica if available, and Geneva °dONLNd
  5779. `0v<˛(Xîif not. How can I determine°dONLNd
  5780. |<<HØ(dZNwhich fonts are available in a printer? I’ve been using the wDev field in the °dONLNd
  5781.  <ØH˛(dÕprint record and°dONLNd
  5782. €H<T§(pZassuming that a value °dONLNd
  5783. ÒH§T˛)hIof 3 means Helvetica will print correctly, but according to “Print Hints:°dONLNd ;T<`„(|Z!Top 10 Printing Misdemeanors” in °dONLNd \T„`)ßdevelop°dONLNd cT`û)%! issue 12, this isn’t dependable.°dONLNd Ö`<lN(àZ___ ¡X¡
  5784. *NPR 510 - Printer Driver Q&As(÷ˇ3) of 21(ÏZM.PR.PrtDvr.Q&AsˇÓ◊#ˇ ˇˇˇˇ#◊ 
  5785. IR,Times
  5786. .+6-Macintosh Technical Notes /4/˘
  5787. °dONLNd)*6There’s no procedural way to ask a printer if it even °dONLNd6)⁄)˜,has built-in fonts, let alone what they are.°dONLNdc)5F(Q6=By using wDev == 3, you’ve been assuming that all PostScript °dONLNd†)F5⁄(Qd printers have built-in Helvetica°dONLNd¡5A©(]6Sfonts, and while most do, some do not. There are several things you can do, though.°dONLNdMYÿ*$First of all, you should know about °dONLNd9MÿY⁄)¿3font substitution. If this option is checked in the°dONLNdmYe˜(Å6.LaserWriter driver (it’s checked by default), °dONLNdõY˜e⁄)fl+you’ll get Helvetica instead of Geneva when°dONLNd«eq~(ç6Idrawing in Geneva on PostScript printers that have Helvetica. The driver °dONLNde~q⁄(çúadjusts all the font°dONLNd%q}(ô6metrics so the widths °dONLNd;q}⁄)gEmatch what you see on the screen. In some versions of the LaserWriter°dONLNdÅ}â;(•6driver, °dONLNdâ};â⁄)#Syou’ll get Geneva instead—but only if the Geneva TrueType font is available, so you°dONLNd›âï£(±6Tget excellent quality either way. This might be enough to solve your entire problem.°dONLNd2°≠D*<If not, there’s the new PSWriter driver on AppleLink and on °dONLNdn°D≠W(…bthe °dONLNdr°W≠æ)Developer CD Series°dONLNdÖ°æ≠⁄)g disc.°dONLNdå≠π`(’6EPSWriter uses PostScript Printer Definition (PPD) files and supports °dONLNd—≠`π⁄(’~a new PrGeneral call that°dONLNdÎπ≈Ü(·6Klets you obtain the PPD file so that you can know things about your target °dONLNd6πÜ≈⁄(·§printer, including°dONLNdI≈—Œ(Ì6]what fonts are installed. While this might give misleading results if the user has never set °dONLNd¶≈Œ—⁄(ÌÏup°dONLNd©—›ö(˘6Vthe printer (and is using the Generic PPD), it should be just fine in all other cases.°dONLNdÈı„*(There’s no way to tell whether the user °dONLNd(È„ı⁄)À0has downloaded a font to the PostScript printer,°dONLNdYıÕ(6_making it available, because it won’t be in the PPD file and there’s no way to ask the printer.
  5788. °dONLNdπ(Ö*'6Where to get PostScript Printer Definition (PPD) files
  5789. °dONLNd(4x* Date written:  2/9/93°dONLNd4@Å* Last reviewed:  4/1/93°dONLNdLXº*ZWhere can I get PostScript Printer Definition (PPD) files for Apple’s PostScript printers?°dONLNdxXd** ___°dONLNd|p|¨*SApple recently made PPD files for its printers—past and present—available. You can °dONLNdœp¨|⁄(ò     find them°dONLNdŸ|àÄ(§6Con AppleLink in the Software Sampler: Apple SW Updates: Macintosh: °dONLNd|Äà⁄(§ûPrinting Software:°dONLNd/àîV(∞6 PPDs folder.°dONLNd<†¨È*,PPD files for non-Apple PostScript printers °dONLNdh†È¨⁄)—-with ROMs by Adobe Systems are available from°dONLNdñ¨∏ù(‘6a clearinghouse maintained °dONLNd±¨ù∏⁄)Ö<by Adobe. To request a PPD file from Adobe, send an internet°dONLNdÓ∏ƒè(‡6Gmessage to “ps-file-server@adobe.com” with the subject “help”. Adobe’s °dONLNd5∏èƒ⁄(‡≠list server will°dONLNdFƒ–¶(Ï6Trespond with mail about items available on the list server and how you can get them.
  5790. °dONLNdõ˘N*',LaserWriter Driver 7.2 isn’t ColorSync aware
  5791. °dONLNd»˜~* Date written:  1/11/93°dONLNdflÅ* Last reviewed:  4/1/93°dONLNdˆ'Í**Is LaserWriter Driver 7.2 ColorSync aware?°dONLNd    !'3** ___°dONLNd    %?Ki*ENo, LaserWriter Driver 7.2 isn’t ColorSync aware. Apple plans to add °dONLNd    j?iK⁄(gáColorSync capability to°dONLNd    ÇKWq(s6Ffuture versions of the LaserWriter driver, but we don’t have any more °dONLNd    »KqW⁄(sèinformation or details°dONLNd    flWcD(6
  5792. than that. ¡4¡˘
  5793. *W4) of 21(÷|PR 510 - Printer Driver Q&As+(M.PR.PrtDvr.Q&Asˇ∂◊#ˇ ˇˇˇˇ#◊ 
  5794. IR,Times
  5795. .+Z-Developer Support Center(-€September 1993 /X/
  5796. °dONLNd<,9(HZ$Printing nonstandard page dimensions
  5797. °dONLNd%,<8¢* Date written:  1/14/93°dONLNd<8<D´* Last reviewed:  6/14/93°dONLNdTP<\›* How do we override the standard °dONLNdtP›\˛)°<page dimensions for the StyleWriter or, for that matter, any°dONLNd±\<h{(ÑZFother printer? We want to print 5.5" x 8.5" (half letter-sized) pages.°dONLNd¯h<tN* ___°dONLNd¸Ä<åù*The current printing °dONLNdÄùåù)a6architecture isn’t designed for elegant (or sometimes °dONLNdGÄùå≤(®ªany)°dONLNdKÄ≤å˛) communication°dONLNdZå<ò6(¥Z7from your program to the printer driver. All the calls °dONLNdëå6ò˛)˙%you normally make (such as PrOpenDoc,°dONLNd∑ò<§Ö(¿ZEPrOpenPage, and PrPicFile) are handled by the printer driver and not °dONLNd¸òÖ§˛(¿£by the Printing Manager.°dONLNd§<∞≠(ÃZThe drivers manage the °dONLNd,§≠∞˛)qEprint records, put up the dialog boxes, decide how to render graphics°dONLNdr∞<º≠(ÿZOand everything else in between. That’s why writing a printer driver is so hard.°dONLNd¬»<‘£*RIf you want to tell a printer driver “I want to use this size paper,” that driver °dONLNd»£‘˛(¡has to implement a°dONLNd'‘<‡L(¸Z:driver-specific way to do it or it can’t be done. There’s °dONLNda‘L‡˛(¸j$no PrSetPageSize call in the current°dONLNd܇<ϰ(ZLprinting architecture. In fact, trying to print outside the rPage rectangle °dONLNd“‡°Ï˛(øcan cause physical°dONLNdÂÏ<¯–(ZPdamage on some printers, so customizing page sizes is not something you want to °dONLNd5Ï–¯˛(Ó
  5798. enter into°dONLNd@¯<^( Zlightly.°dONLNdI<Ô*^You can’t change the paper size in the print record, because most drivers don’t look there to °dONLNdßÔ˛(8
  5799. see°dONLNd´<(k(DZ
  5800. what size °dONLNdµk(Å)/you °dONLNdπÅ(õ)want;°dONLNdæõ(K)% instead they tell you what size you °dONLNd„K(])∞get °dONLNdÁ](˛)#in that field. The same is true for°dONLNd (<4’(PZ!most of the print record: Unless °dONLNd,(’4&)ôInside Macintosh°dONLNd<(&4})Q tells you that you °dONLNdP(}4˛)Wcan write to that field, you°dONLNdm4<@ı(\Z&can’t (or doing so won’t do any good).°dONLNdîL<Xß*QThe StyleWriter in particular has very limited paper options; it handles letter, °dONLNdÂLßX˛(t≈legal, A4, and B5°dONLNd˜X<dH(ÄZ<paper sizes—and that’s it. If you try to print other sizes, °dONLNd3XHd˛(Äf&the hardware reports an error. This is°dONLNdZd<p—(åZRpretty common in these days of very low-cost high-quality printers; features that °dONLNd¨d—p˛(åÔyou as a°dONLNdµp<|∑(òZprogrammer would want °dONLNdÀp∑|˛){Bare jettisoned to keep the cost down. Most low-cost laser printers°dONLNd|<à!(§Z2have limited paper-handling capabilities as well. °dONLNd@|!à˛)Â.If you try to print continuous feed paper on a°dONLNdoà<îµ(∞ZStyleWriter, you’ll get a °dONLNdâàµî˛)yApaper jam error after about 15 inches of paper pass through (long°dONLNdÀî<†Ô(ºZ_enough for the printer to realize it’s not legal-sized paper). Your half-letter size pages are °dONLNd*îÔ†˛(º
  5801. too°dONLNd.†<¨ª(»Zshort for the printer to use.°dONLNdL∏<ƒ…*While QuickDraw GX has a °dONLNde∏…ƒ˛)ç?much more robust printing architecture, that doesn’t help right°dONLNd•ƒ<–µ(ÏZMnow for the current world. Something that you may wish to consider is making °dONLNdÚƒµ–˛(Ï”forms available°dONLNd    –<‹è(¯ZIon regular letter-sized paper, with two per sheet. That size paper works °dONLNd    K–è‹ú(¯≠in °dONLNd    N–ú‹∂)
  5802. every°dONLNd    S–∂‹˛) printer sold in°dONLNd    d‹<Ëï(ZHthe United States and could be perforated and detached by the customers.°dONLNd    ≠Ù<F*9All of Apple’s LaserWriter printers have excellent paper °dONLNd    ÊÙF˛(d&handling but cost relatively more. The°dONLNd
  5803.  
  5804. < ((Z/best way to handle custom page printing across °dONLNd
  5805. < ))‚all°dONLNd
  5806. ?) j)  printers is to °dONLNd
  5807. Oj ˛)Aplace your custom-sized image°dONLNd
  5808. m <#(4Z0on an 8.5" x 11" page and provide special paper.°dONLNd
  5809. û$<0≤*OMany, but not all, of Apple’s printers support a PREC 3 resource that contains °dONLNd
  5810. Ì$≤0˛(L–extra page sizes°dONLNd
  5811. ˛0<<](XZ>in a custom format. The format of this resource is as follows:,
  5812. Courier
  5813.     °dONLNd =H<S¥* PageSizeRecord = RECORD°dONLNd VR<]†*
  5814.   numItems: INTEGER;°dONLNd k\<g6*
  5815. 2  botRights: ARRAY [0..NumPageOptionsZB] OF Point;°dONLNd ûf<q˙*
  5816. &  titles: PACKED ARRAY [0..0] OF CHAR;°dONLNd ≈p<{U*
  5817.  END; ¡X¡
  5818. *?PR 510 - Printer Driver Q&As(÷ˇ5) of 21(ÏZM.PR.PrtDvr.Q&Asˇ§◊#ˇ ˇˇˇˇ#◊ 
  5819. IR,Times
  5820. .+6-Macintosh Technical Notes /4/˘
  5821. °dONLNd)*2numItems is the number of page sizes displayed in °dONLNd2)⁄)˙%the dialog. The maximum number is six°dONLNdX)5Û(Q60(since there is only room for six radio buttons °dONLNdà)Û5⁄)€0in the Page Setup dialog). botRights is an array°dONLNdπ5Aü(]6Uof points specifying the bottom right corner for each page. This corner is specified °dONLNd5üA⁄(]Ω in 120ths of°dONLNdAM≠(i6an inch, and it should define °dONLNd9A≠M⁄)ï;the physical size of the paper, not the imageable area. For°dONLNduMYƒ(u6%example, U.S. Letter is specified as:,
  5822. Courier
  5823.     °dONLNdõepÔ*+    bottom = 1320(11"), right = 1020(8.5").
  5824. °dONLNd»{áê*titles is a packed array of °dONLNd‰{êá⁄)xApage size names. Each name begins with a length byte, followed by°dONLNd&áìˇ(Ø6*the number of characters specified by the °dONLNdPáˇì⁄)Á'length byte. The strings are packed, so°dONLNdxìüs(ª6Fstring1[LENGTH(string1)+1] would reference the length byte of string2.°dONLNd¿´∑§*To use this mechanism, your °dONLNd‹´§∑⁄)å=application should create a PREC resource with an ID = 4. You°dONLNd∑√
  5825. (fl61can do this very easily by copying PREC(3). Once °dONLNdK∑
  5826. √⁄)Ú(you have a copy, you can modify the page°dONLNdt√œ[(Î6Dsizes as you wish. When the printer driver is called to display the °dONLNd∏√[œ⁄(ÎyPage Setup dialog, it will°dONLNd”œ€(˜6;first look for PREC(4). If found, it will use it to define °dONLNdœ€⁄(˜<(the page sizes. If not found, the driver°dONLNd7€Á“(6'will use the standard sizes in PREC(3).°dONLNd_Ûˇ*,This method only works with some of Apple’s °dONLNdãÛˇ⁄)Ë-drivers; the LaserWriter driver ignores these°dONLNdπˇ ('66resources. If you decide to implement this feature in °dONLNdÔˇ ⁄('7&your application, be sure to warn your°dONLNd G(36Ausers that custom page sizes may not be available on all devices.°dONLNdX#/â*Use this feature at your °dONLNdq#â/⁄)qCown risk; it’s very likely not to work under QuickDraw GX and later°dONLNdµ/;i(W6system software.
  5827. °dONLNdΔSbo*'2LaserWriter driver 'feed' resource troubleshooting
  5828. °dONLNd˘bnÑ* Date written:  11/24/92°dONLNdnzÅ* Last reviewed:  3/1/93°dONLNd(ÜíÈ*+The userdict definitions in my LaserWriter °dONLNdSÜÈí⁄)—1driver 'feed' resource (written per the Macintosh°dONLNdÖíû”(∫6$Technical Note “Feeder Fodder”) get °dONLNd©í”û⁄)ª2wiped out after each page. At least, every time my°dONLNd‹û™
  5829. (Δ62redefined showpage is executed the variables that °dONLNdû
  5830. ™⁄)Ú*should have been defined the first time in°dONLNd9™∂æ(“6Uuserdict are unbound. What could be happening here? How should I define something in °dONLNd陿∂⁄(“‹'feed'°dONLNdï∂¬f(fi6Hresource code that acts like a global variable for a redefined showpage?°dONLNdfi¬Œ** ___°dONLNd‚⁄Ê“*&Your operators shouldn’t be wiped out °dONLNd⁄“Ê⁄)∫3with each page. You’re being loaded before the PREC°dONLNd<ÊÚı(6,103 is loaded and before the series of save °dONLNdhÊıÚ⁄)›-and restore operators are called, which could°dONLNdñÚ˛æ(6otherwise wipe you out. Please °dONLNdµÚæ˛⁄)¶1read the Macintosh Technical Note “The Lo Down on°dONLNdÁ˛
  5831. Å(&6KDictionary Downloading” for a robust description of this process. Thus, we °dONLNd    2˛Å
  5832. ⁄(&ümust look to other°dONLNd    E
  5833. (26/reasons why your operators are being wiped out.°dONLNd    u".·*,The natural culprit is your PostScript. Are °dONLNd    °"·.⁄)…0you wiping yourself out? Second, you should heed°dONLNd    “.:‚(V6%the warning on page 4 of the “Feeder °dONLNd    ˜.‚:⁄) .Fodder” Technical Note: “As always, calling or°dONLNd
  5834. &:F
  5835. (b63redefining operators defined by the LaserPrep (md) °dONLNd
  5836. Y:
  5837. F⁄)ı*dictionary isn’t supported.” You could see°dONLNd
  5838. ÑFRW(n6Cproblems as you describe if you’re redefining LaserPrep dictionary °dONLNd
  5839. «FWR⁄(nucommands. Other variables°dONLNd
  5840. ·R^N(z6 include the °dONLNd
  5841. ÌRN^⁄)6Qsystem software and LaserWriter driver versions that you’re using. It could be an°dONLNd ?^j÷(Ü6*issue with the type of LaserWriter itself. ¡4¡˘
  5842. *P6) of 21(÷|PR 510 - Printer Driver Q&As+(M.PR.PrtDvr.Q&Asˇ÷◊#ˇ ˇˇˇˇ#◊ 
  5843. IR,Times
  5844. .+Z-Developer Support Center(-€September 1993 /X/
  5845. °dONLNd<,Î(HZ;LaserWriter driver doesn’t SwapMMUMode for 32-bit addresses
  5846. °dONLNd<,<8®* Date written:  11/17/92°dONLNdT8<D´* Last reviewed:  6/14/93°dONLNdlP<\›*When I use CopyBits to move a °dONLNdäP›\˛)°8cGrafPort’s portPixMap to another cGrafPort (my printing°dONLNd√\<hc(ÑZ
  5847. port), it °dONLNdÕ\ch˛)'Pworks like a charm when background printing is turned on, but when CopyBits gets°dONLNdh<t (êZ,called with background printing turned off, °dONLNdJh t˛)œ4the image that prints isn’t the image at all. Why is°dONLNdt<ÄÜ(úZthis happening?°dONLNdèÄ<åN* ___°dONLNdìò<§î*BYou should be aware that since you’re copying the pixels directly °dONLNd’ò(¿≤from the screen, the°dONLNdͧ<∞n(ÃZ    baseAddr °dONLNdÛ§n∞˛)2Mpointer for the screen’s pixMap may be 32-bit addressed. In fact, with 32-Bit°dONLNdA∞<º®(ÿZLQuickDraw, this is the case. This in itself isn’t a problem, since CopyBits °dONLNdç∞®º˛(ÿΔknows enough to°dONLNdùº<»m(‰Z?access the port’s pixMap’s baseAddr in 32-bit mode, as follows:,
  5848. Courier
  5849.     °dONLNd›‘<flá*mode = true32b;°dONLNdÌfi<ÈÜ*
  5850. BSwapMMUMode(&mode);  // Make sure we're in 32-bit addressing mode.°dONLNd0Ë<ÛJ*
  5851. 6// Access pixels directly; make no other system calls.°dONLNdgÚ<˝1*
  5852. 1SwapMMUMode(&mode);  // Restore the current mode.
  5853. °dONLNdô<E*4That’s how you’d normally handle things if you were °dONLNdÕE˛(0c'accessing the pixels directly yourself.°dONLNdı< (<Z.Unfortunately, the LaserWriter driver doesn’t °dONLNd# ˛)fl%know enough to do the SwapMMUMode and°dONLNdI <,«(HZUinstead ends up copying garbage (from a 32-bit pointer stripped to a 24-bit pointer).°dONLNdü8<DO*So °dONLNd¢8OD˛)Lwhy does background printing work? Because when you print in the background,°dONLNdÔD<Pÿ(lZ"everything is rolled into a PICT, °dONLNdDÿP˛)ú=which the driver saves off for PrintMonitor. Since the driver°dONLNdOP<\u(xZ
  5854. is using the °dONLNd\Pu\˛)9Mstandard QuickDraw picture bottlenecks to do this, and CopyBits knows to swap°dONLNd™\<hN(ÑZthe °dONLNdÆ\Nh˛)TMMU mode before copying the data into the picture, everything works great. Later, at°dONLNdh<t2(êZ5PrintMonitor time, the picture is played back. Since °dONLNd8h2t˛)ˆ+the data is no longer 32-bit addressed, the°dONLNddt<Äñ(úZLaserWriter driver °dONLNdwtñIJ)ZHdoesn’t have to call SwapMMUMode to do the right thing; it can just play°dONLNd¿Ä<åä(®Zthe picture back.°dONLNd“ò<§Â*#The solution we propose for you is °dONLNdıò§˛)©8something similar. At print time (before your PrOpenPage°dONLNd.§<∞
  5855. (ÃZ,call), call OpenPicture, copy the data from °dONLNdZ§
  5856. ∞˛)—0the screen with CopyBits, call ClosePicture, and°dONLNdã∞<ºÏ(ÿZXthen call DrawPicture within your PrOpenPage/PrClosePage loop. That should do the trick.°dONLNd‰»<‘Δ*ONote that copying bits directly from the screen is not something we recommend. °dONLNd3»Δ‘˛(‰
  5857. Unless you°dONLNd>‘<‡”(¸Z have no alternative, you should °dONLNd^‘”‡Ù)óalways°dONLNdd‘Ù‡fi)!3 copy from the original source of the data instead.
  5858. °dONLNdò¯<`(#Z+System 7.1 and printer driver compatibility
  5859. °dONLNdƒ<®* Date written:  11/18/92°dONLNd‹<´* Last reviewed:  6/14/93°dONLNdÙ+<7Δ*OIf a user upgrades from System 7.0.x to 7.1, a new version of the PrintMonitor °dONLNd    C+Δ7˛(S‰
  5860. is installed.°dONLNd    Q7<Cì(_ZIWill existing printer drivers behave correctly with the new PrintMonitor?°dONLNd    õC<ON* ___°dONLNd    ü[<gû*When a user installs °dONLNd    ¥[ûg˛)bJSystem 7.1, Easy Install will update any existing printer software. If the°dONLNd    ˇg<s∂(èZuser picks Customize, he °dONLNd
  5861. g∂s˛)zCor she must choose the printers to be updated. Only the versions of°dONLNd
  5862. \s<≤(õZNthe printer drivers that come with System 7.1 should be used with 7.1. Mixing °dONLNd
  5863. ™s≤˛(õ–and matching is°dONLNd
  5864. ∫<ãQ(ßZbad. ¡X¡
  5865. */PR 510 - Printer Driver Q&As(÷ˇ7) of 21(ÏZM.PR.PrtDvr.Q&Asˇr◊#ˇ ˇˇˇˇ#◊ 
  5866. IR,Times
  5867. .+6-Macintosh Technical Notes /4/˘
  5868. °dONLNd)*8Since only Apple’s printer drivers use PrintMonitor, as °dONLNd8)⁄(E=$long as you upgrade to System 7.1 by°dONLNd])5÷(Q6,using the Installer there’s no issue at all.
  5869. °dONLNdäM\ *'"System 6 and System 7 PrintMonitor
  5870. °dONLNd≠\hÑ* Date written:  11/18/92°dONLNd≈htÅ* Last reviewed:  3/1/93°dONLNd‹Äå*6Is the version of PrintMonitor that ships with System °dONLNdÄå⁄(®=$7.1 compatible with System 6? If so,°dONLNd7åò§(¥6Qwhich version of the Backgrounder file would be compatible for installation with °dONLNdàå§ò⁄(¥¬
  5871. the System°dONLNdìò§fi(¿6'7.1 PrintMonitor on System 6.x systems?°dONLNdª§∞** ___°dONLNdøº»H*>Only Apple’s printer drivers should be using PrintMonitor—the °dONLNd˝ºH»⁄(‰finterface is undocumented and°dONLNd»‘i(6unsupported for °dONLNd+»i‘⁄)QNother printer drivers. PrintMonitor-like things are a different story, but the°dONLNdz‘‡Ö(¸6Lspecific Apple product PrintMonitor works only with Apple’s printer drivers.°dONLNd«Ï¯â*LWhile the drivers may be used under System 6, users should use the versions °dONLNdÏâ¯⁄(ßof Backgrounder°dONLNd#¯ã( 6Kand PrintMonitor present on the System 6.0.8 disks. Since Backgrounder and °dONLNdn¯ã⁄( ©PrintMonitor are°dONLNdº(,6Vtied together, we have to recommend against using the 7.1 PrintMonitor under System 6.°dONLNd÷(d*Note that in all °dONLNdÁd(ç)L;these cases, nothing was specifically added to make things °dONLNd"ç(ú(D´not°dONLNd%ú(⁄)  work under°dONLNd1(4k(P6ESystem 6—they simply weren’t tested and therefore can’t be supported.°dONLNdw@LI*Summary:°dONLNdÄXd_*BSystem 6: Backgrounder and PrintMonitor from 6.0.8, current driver°dONLNd√dpÌ* .System 7: Use whatever the Installer installs.
  5872. °dONLNdÚàóÂ*'Which printers to test printing
  5873. °dONLNdó£~* Date written:  10/1/92°dONLNd)£Øá* Last reviewed:  11/2/92°dONLNdAª«ô*OWe need to know what printers on which to test our application. It prints only °dONLNdêªô«⁄(„∑
  5874. pixmaps. It’s°dONLNdû«”^(Ô6been tested on °dONLNd≠«^”⁄)FJsome LaserWriters. The question is, how many brands and models of printers°dONLNd¯”fl>(˚6Bdo we need to test it on? Are there any definitive printing tests °dONLNd:”>fl⁄(˚\(for example, does success on a°dONLNdZflÎ (65LaserWriter indicate correctness of the application)?°dONLNdêΘ** ___°dONLNdî>*>Unfortunately, there is no such thing as a universal printing °dONLNd“>⁄(+\ test suite. Moreover, successful°dONLNdÛ
  5875. (762printing not only depends on the specific printer °dONLNd%
  5876. ⁄)ı)driver (and its version), but also on the°dONLNdO'(C6.available memory at print time, and on things °dONLNd}'⁄)ÿ1like the font configuration in the system. (Given°dONLNdØ'3˚(O6.that you print pixmaps only, the last comment °dONLNd›'˚3⁄)„0is not applicable. Most certainly, all potential°dONLNd3?([60problems will rather boil down to out of memory °dONLNd>3?⁄)Í,conditions). Also, we have seen applications°dONLNdk?Kô(g6with severe defects in their °dONLNdà?ôK⁄)ÅEprinting code print quite correctly to the LaserWriter, and fail only°dONLNdŒKW”(s6'on a few other specific printers. Most °dONLNdıK”W⁄)ª3other printing problems have to do with assumptions°dONLNd    )Wcl(6Jabout the inner working of a specific printer driver, such as hacking the °dONLNd    sWlc⁄(äprint record behind the°dONLNd    ãco≤(ã6Vback of the Printing Manager. In this case, trouble with at least one of the 150 plus °dONLNd    ·c≤o⁄(ã–    different°dONLNd    Îo{Ã(ó6(printer drivers out there is guaranteed! ¡4¡˘
  5877. *?8) of 21(÷|PR 510 - Printer Driver Q&As+(M.PR.PrtDvr.Q&Asˇt◊#ˇ ˇˇˇˇ#◊ 
  5878. IR,Times
  5879. .+Z-Developer Support Center(-€September 1993 /X/
  5880. °dONLNd<)E(EZ6Pragmatically speaking, you may want to test printing °dONLNd6E)˛(Ec'in priority on the printers most likely°dONLNd^)<5[(QZbeing °dONLNdd)[5˛)Oused by your customers. Currently (as of November 1992), this is the PostScript°dONLNd¥5<Av(]ZELaserWriter (driver version 7.1.2 or later), the StyleWriter (driver °dONLNd˘5vA˛(]îversion 7.2.2), the Personal°dONLNdA<My(iZ LaserWriter °dONLNd"AyM˛)=KLS (driver version 7.2), and one or another of the most popular third-party°dONLNdnM<Y(uZVprinters. In addition, we recommend that you test both on an older LaserWriter (up to °dONLNdƒMY˛(uthe°dONLNd»Y<e(ÅZLaserWriter II
  5881. °dONLNd÷Yeå)CNT
  5882. °dONLNdÿYåeG)
  5883. (), and the newer ones (LaserWriter IIf, °dONLNdYGe˛)ª%IIg, NTR), because of the differences°dONLNd&e<q3(çZ6in the PostScript interpreters and gray-level support.
  5884. °dONLNd]â<ò˘*'@Where to get documentation on writing a Macintosh printer driver
  5885. °dONLNdûò<§û* Date Written:  4/9/91°dONLNd¥§<∞•* Last reviewed:  8/1/92°dONLNdÀº<»‚*UWhere can I find documentation on how to write a Macintosh printer driver equivalent °dONLNd º‚»˛(‰to the°dONLNd'»<‘,(Z2ImageWriter or LaserWriter driver? In particular, °dONLNdY»,‘˛)&how are Printing Manager and QuickDraw°dONLNdÄ‘<‡/(¸Z5commands translated into calls to the printer driver?°dONLNd∂‡<ÏN* ___°dONLNd∫¯<¬*CDTS’s “Learning to Drive” document and “StdFileSaver” source code, °dONLNd˝¯¬˛( ‡ available in°dONLNd
  5886. <    (,Z)AppleLink’s Developer Support folder and °dONLNd3    C)Õ
  5887. on the latest°dONLNd@C¨): Developer CD Series°dONLNdT¨˛)i disc, are helpful°dONLNdg<p(8Z references.
  5888. °dONLNds4<C'*'"Writing a Macintosh printer driver
  5889. °dONLNdñC<Oû* Date Written:  5/3/89°dONLNd¨O<[•* Last reviewed:  8/1/92°dONLNd√g<s¥*I have a printer I would °dONLNd‹g¥s˛)xAlike to connect to the Macintosh. Where can I find information on°dONLNds<¨(õZwriting a printer driver?°dONLNd8<ãN* ___°dONLNd<ó<£ù*LA Macintosh printer driver is more than a standard device driver. A printer °dONLNdàóù£˛(øªdriver contains code°dONLNdù£<Øü(ÀZto implement all of °dONLNd±£üØ˛)cCthe standard Macintosh Printing Manager routines. The code includes°dONLNdıØ<ª[(◊Z8routines like PrOpen/PrClose, and PrOpenDoc/PrCloseDoc. °dONLNd-Ø[ª˛(◊y!A Printing Resource File contains°dONLNdOª<«L(„Zall °dONLNdSªL«˛)Sof the resources (including code) to implement the Macintosh Printing Manager for a°dONLNdß«<”T(ÔZ:particular device. A driver works best with all Macintosh °dONLNd·«T”˛(Ôr$applications if it supports both the°dONLNd”<fll(˚Z
  5890. high- and °dONLNd”lfl˛)0Rlow-level Printing Manager interfaces, as well as the PrGeneral (IM V:410) routine°dONLNdcfl<κ(Zand its associated opcodes.°dONLNd˜<›*XApple is not currently supporting the development of Chooser-selectable device drivers, °dONLNd◊˜›˛(˚at least°dONLNd‡<Ó(+Z'not those that support printers. There °dONLNdÓ˛)≤9are many reasons for this, and here are at least a few of°dONLNdA<V(7Zthem:°dONLNdG'<3ë*First, there is no °dONLNdZ'ë3˛)UIdocumentation or examples available. Each of the Apple printer drivers is°dONLNd§3<?÷([ZWunique. They are all written almost entirely in 68000 assembler, and consequently, are °dONLNd˚3÷?˛([Ùnot very°dONLNd    ?<K#(gZ2easy to read. Since each driver is different, the °dONLNd    6?#K˛)Á+only real documentation for how the drivers°dONLNd    bK<Wæ(sZSwork is the source code to the driver. There is some general interface information °dONLNd    µKæW˛(s‹available, but°dONLNd    ƒW<cb(Z=important information, like how the driver manages its print °dONLNd
  5891. Wbc˛(Ä record, is described only in the°dONLNd
  5892. "c<oí(ãZIsource code. This information could be extracted and distilled into some °dONLNd
  5893. kcío˛(ã∞kind of document, but°dONLNd
  5894. Åo<{“(óZ this brings up the next problem: ¡X¡
  5895. *?PR 510 - Printer Driver Q&As(÷ˇ9) of 21(ÏZM.PR.PrtDvr.Q&Asˇ‹◊#ˇ ˇˇˇˇ#◊ 
  5896. IR,Times
  5897. .+6-Macintosh Technical Notes /4/˘
  5898. °dONLNd)0*:The Macintosh Printing Manager is currently being revised °dONLNd:0)⁄(EN"and enhanced. These revisions will°dONLNd])5ì(Q6require major changes to °dONLNdv)ì5⁄){Dthe architecture of the Printing Manager. It’s not clear what effect°dONLNdª5Aq(]6these changes will °dONLNdŒ5qA⁄)YOhave on existing printer drivers, but it is very possible that the drivers that°dONLNdAM≥(i6Xexist today will have to be revised significantly to run under the new Printing Manager.°dONLNdwYeF*8Apple is designing and implementing the next generation °dONLNdØYFe⁄(ÅdMacintosh Printing Manager.°dONLNdÀeqR(ç6CDevelopers’ suggestions for features are being taken into account. °dONLNdeRq⁄(çpOne of the goals of the new°dONLNd*q}4(ô6=architecture is to make writing drivers much simpler, and to °dONLNdgq4}⁄(ôR!allow the sharing of code between°dONLNdâ}â_(•6drivers. When °dONLNdó}_â⁄)GQthis architecture becomes available, Apple will reconsider its position of driver°dONLNdÈâï±(±6development, and will probably °dONLNdâ±ï⁄)ô;end up with some kind of licensing agreement for developers°dONLNdDï°ë(Ω6Qthat want to write drivers. Until then, the preceding reasons should be adequate °dONLNdïïë°⁄(ΩØjustification for°dONLNdß°≠(…67NOT attempting a Macintosh printer driver at this time.°dONLNdflπ≈œ*(If you still aren’t convinced, and want °dONLNdπœ≈⁄)∑;to write a driver despite the challenge, see the article in°dONLNdC≈—ñ(Ì6the December ’88 issue of °dONLNd]≈ñ—ƒ)~MacTutor°dONLNde≈ƒ—ú).. magazine. There is an example printer driver °dONLNdì≈ú—⁄)ÿ
  5899. written in C.°dONLNd°—›˜(˘62It is just a skeleton driver, and does not handle °dONLNd”—˜›⁄)fl/any of the more difficult problems such as line°dONLNd›Èt(6Nlayout, font substitution, graphics, or banding. But it is a start, and gives °dONLNdQ›tÈ⁄(íyou a general idea of°dONLNdgÈı∂(6!the structure of a driver. Since °dONLNdàÈ∂ı⁄)û8some developers began writing their drivers before Apple°dONLNd¡ı:(67discontinued support, DTS is still answering questions °dONLNd¯ı:⁄(Xconcerning driver development.°dONLNd
  5900. w()6JHowever, these questions are limited to those that can be answered by the °dONLNdaw
  5901. ⁄()ïDTS engineers. You°dONLNdt
  5902. ª(56"should also be aware that some of °dONLNdñ
  5903. ª⁄)£;the techniques used by Apple printer drivers are considered°dONLNd“%«(A6Wproprietary. Information on methods used for line layout as well as certain aspects of °dONLNd)«%⁄(AÂfont°dONLNd.%1©(M6handling will not be disclosed.°dONLNdN=I9*X-Ref:°dONLNdUIUj* Printing Manager
  5904. °dONLNdfm|ñ*'9Changing printer driver settings without using the dialog
  5905. °dONLNd†|àÄ* Date Written:  11/6/91°dONLNd∑àîá* Last reviewed:  6/14/93°dONLNdœ†¨r*To change default °dONLNd·†r¨⁄)ZJprinter driver settings without using the dialog, keep a copy of the print°dONLNd,¨∏ (‘6[record with the various settings you want, and when you want to choose your settings, just °dONLNdᨠ∏⁄(‘Ëuse°dONLNdã∏ƒV(‡6
  5906. your special °dONLNdò∏Vƒ⁄)>Oprint record. The current Macintosh print architecture doesn’t allow procedural°dONLNd˃–D(Ï6Baccess to the print record, so you must call the dialogs once for °dONLNd    *ƒD–⁄(Ïbyourself, choose your settings,°dONLNd    J–‹'(¯6;and then save a copy of the print record that is produced. °dONLNd    Ö–'‹⁄(¯E$Some settings are job-dependent, but°dONLNd    ™‹Ë(67values that are retrieved from the print record can be °dONLNd    ·‹Ë⁄(8%changed using this technique. You can°dONLNd
  5907. ËÙ0(6only °dONLNd
  5908. Ë0Ù⁄)Zsave the settings in the Style dialog. Call PrValidate when retrieving a print record from°dONLNd
  5909. gÙ‰(6,the resource fork to make sure it is “good.”°dONLNd
  5910. ï -*See °dONLNd
  5911. ô -R)develop°dONLNd
  5912. † R⁄)%N, issue #1, pages 58–65, for a complete discussion of changing default printer°dONLNd
  5913. Ô$∞(@6 driver settings and sample code.
  5914. °dONLNd <K*'!Macintosh print record wDev field
  5915. °dONLNd 2KWz* Date Written:  5/3/89°dONLNd HWcÅ* Last reviewed:  8/1/92°dONLNd _o{™*RWhat is the Macintosh print record wDev value for the ImageWriter LQ, LaserWriter °dONLNd ±o™{⁄(ó»    IISC, and°dONLNd ª{ár(£6AppleFax Modem?°dONLNd Àáì** ___ ¡4¡˘
  5916. *'10)
  5917.  of 21(÷|PR 510 - Printer Driver Q&As+(M.PR.PrtDvr.Q&AsˇJ◊#ˇ ˇˇˇˇ#◊ 
  5918. IR,Times
  5919. .+Z-Developer Support Center(-€September 1993 /X/
  5920. °dONLNd)<5ù(QZIApple strongly discourages the use of the wDev field in the print record °dONLNdI)ù5˛(Qªfor several reasons.°dONLNd^5<A(]Z'First, this field contains a unique ID °dONLNdÖ5A˛)¥5for each printer driver on the Macintosh. Coding your°dONLNdªA<Mr(iZ application °dONLNd«ArM˛)6Oto use this ID makes it device dependent, and device dependence will cause many°dONLNdM<Yr(uZ9problems in the future as the Macintosh Printing Manager °dONLNdPMrY˛(uêcontinues to evolve. Many°dONLNdjY<e¶(ÅZapplications currently °dONLNdÅY¶e˛)jBcheck for wDev = 3 to determine whether or not to send PostScript.°dONLNdƒe<qG(çZ1Although the Apple LaserWriter driver has a wDev °dONLNdıeGq˛(çe%of 3, third-party printer drivers for°dONLNdq<}”(ôZ!PostScript devices do not, so if °dONLNd<q”}˛)ó=your application determines whether or not to send PostScript°dONLNdz}<âK(•Z6based on wDev alone, your application may incorrectly °dONLNd∞}Kâ˛(•i#print with QuickDraw on third-party°dONLNd‘â<ïr(±Z PostScript °dONLNdflârï˛)6Ldevices. A second problem concerns spoolers and spool files. If a spooler is°dONLNd,ï<°õ(ΩZIinstalled between an application and the printer driver that is going to °dONLNduïõ°˛(Ωπdo the printing, the°dONLNdä°<≠À(…ZUapplication receives the wDev ID of the spooler instead of the target driver. If the °dONLNdfl°À≠˛(…È application°dONLNdÎ≠<π%(’Z0makes assumptions based on this ID, it probably °dONLNd≠%π˛)È.gets unexpected results. In the future, it may°dONLNdJπ<≈Ÿ(·Z#also be possible to redirect spool °dONLNdmπŸ≈˛)ù?files. This means that a file that was originally spooled for a°dONLNd≠≈<—Ù(ÌZ(PostScript printer may be redirected to °dONLNd’≈Ù—˛)∏7a QuickDraw device. If the spool file contains only the°dONLNd
  5921. —<›(˘Z.PostScript representation of the document, it °dONLNd;—›˛)’0will be useless to the QuickDraw device. Despite°dONLNdl›<ÈÁ(ZTthese strong warnings, some developers are convinced they need the wDev values, and °dONLNd¿›ÁÈ˛(there°dONLNdΔÈ<ı(Z]may be some vertical applications where they’re needed. For those cases, here is the current °dONLNd#Èı˛(list°dONLNd(ı<Ú(Z&of wDev IDs for Apple printer drivers:,
  5922. Courier
  5923.     °dONLNdO
  5924. <ˇ*'    Device               wDev (Hi Byte)°dONLNdw<"√*
  5925.     ImageWriter I/II:     1°dONLNdì!<,å*
  5926.     LaserWriter,°dONLNd§+<6•*
  5927.     LaserWriter Plus,°dONLNd∫5<@•*
  5928.     LaserWriter IINT,°dONLNd–?<J√*
  5929.     LaserWriter IINTX:    3°dONLNdÏI<T√*
  5930.     LaserWriter IISC:     4°dONLNdS<^√*
  5931.     ImageWriter LQ:       5°dONLNd$]<h√*
  5932.     AppleFax Modem:      10
  5933. °dONLNd@s<÷*WDTS does not support the use of these constants. They are definitely subject to change.
  5934. °dONLNdòó<¶‡*'=Determining if a printer driver accepts Color QuickDraw calls
  5935. °dONLNd÷¶<≤™* Date Written:  11/21/90°dONLNdÓ≤<æ•* Last reviewed:  8/1/92°dONLNd <÷¿*PHow do you find out if a printer driver accepts Macintosh Color QuickDraw calls?°dONLNdV÷<‚N* ___°dONLNdZÓ<˙Í*'Check to see if the printer driver has °dONLNdÅÓÍ˙˛)Æ<returned a color grafPort to your application after the call°dONLNdæ˙<G("Z8to PrOpenDoc (that is, the port that PrOpenDoc returns).°dONLNd˜<}*
  5936. To determine °dONLNd    }˛)APif the grafPort is color, you need to check to see if rowBytes from the grafPort°dONLNd    U<*}(FZDare less than 0. The following code fragment demonstrates this idea:
  5937.     °dONLNd    ö6<A≥*K(* This function determines if the port passed to it is a color port. If *)°dONLNd    Ê@<Kæ*
  5938. (* so, it returns TRUE. *)°dONLNd
  5939. ^<iE*5FUNCTION ColorPort(portInQuestion: GrafPtr): BOOLEAN;°dONLNd
  5940. 7h<sU*
  5941. BEGIN°dONLNd
  5942. =r<}1*
  5943. 1    IF portInQuestion^.portBits.rowBytes < 0 THEN°dONLNd
  5944. o|<áπ*
  5945.         ColorPort := TRUE°dONLNd
  5946. âÜ<ëd*
  5947.     ELSE ¡X¡
  5948. *)PR 510 - Printer Driver Q&As(÷˙11)
  5949.  of 21(ÏZM.PR.PrtDvr.Q&Asˇˆ◊#ˇ ˇˇˇˇ#◊ 
  5950. IR,Times
  5951. .+6-Macintosh Technical Notes /4/˘,
  5952. Courier
  5953.     °dONLNd(ü*        ColorPort := FALSE;°dONLNd'2,*
  5954. END;
  5955. °dONLNd!IX^*&.Printing in mixed Macintosh System 6/7 network
  5956. °dONLNdPXdÜ* Date Written:  12/11/90°dONLNdhdpÅ* Last reviewed:  8/1/92°dONLNd|à¡* What is the recommended printer °dONLNdü|¡à⁄)©5driver for a network environment with mixed operating°dONLNd’àî‘(∞6Ysystems (such as System 6.0.5 on a Macintosh Plus and 7.0 on two Macintosh IIfx systems)?°dONLNd/î†** ___°dONLNd3¨∏∏* In a mixed 6.0.x/7.0 network we °dONLNdS¨∏∏Œ)†8recommend upgrading all systems to the 7.0 print drivers°dONLNd㨌∏⁄(‘Ï—°dONLNdå∏ƒÑ(‡6Heven systems running 6.0.x. The 7.0 LaserWriter drivers work fine under °dONLNd‘∏у⁄(‡¢system 6.0.x and°dONLNdƒ–q(Ï6Lwill avoid any printer reinitialization problems. Use the 7.0 printing disk °dONLNd1ƒq–⁄(Ïè(or the printing install°dONLNdJ–‹(¯65folder), and launch the Installer from that disk. It °dONLNd–‹⁄)Í/has scripts needed to install 7.0 print drivers°dONLNdØ‹Ët(6on a 6.0.x system. °dONLNd¬‹tËÜ)\Do °dONLNd≈‹ÜËô)not °dONLNd…‹ôË⁄)Fselect the Installer options for printers from the main 7.0 Installer,°dONLNdËÙI(6Abecause these scripts currently are only for systems running 7.0.°dONLNdR W*If a Personal °dONLNd`W ⁄)?LLaserWriter NTR is used on the network, you must upgrade all workstations to°dONLNd≠ •(46Uthe 7.1.1 LaserWriter driver or later. (The NTR requires at least LaserWriter 7.1.1.)
  5957. °dONLNd0?“*'?System 7.0 LaserWriter driver & choosing nonstandard page sizes
  5958. °dONLNdC?Kz* Date Written:  4/8/91°dONLNdYKWá* Last reviewed:  6/14/93°dONLNdqcoí*MWith the System 7.0 version of the LaserWriter driver, when the user selects °dONLNdæcío⁄(ã∞
  5959. Envelope from°dONLNdÃo{ø(ó6Zthe Page Setup dialog, the page size returned by the driver is still a standard page: 8.5 °dONLNd&oø{⁄(ó›x 11.°dONLNd,{á8(£68How do you recommend that applications display the page °dONLNdd{8á⁄(£Vsize when the user has chosen a°dONLNdÑáìÖ(Ø6nonstandard page size?°dONLNdõìü** ___°dONLNdü´∑ß*We recommend that you have °dONLNd∫´ß∑⁄)è>the page preview show a full page instead of an envelope-sized°dONLNd˘∑√!(fl65page. The LaserWriter driver supports a large number °dONLNd.∑!√⁄(fl?&of PostScript devices, and it can’t be°dONLNdU√œû(Î6Wsure whether the envelope will be fed on the right, left, or center of the paper tray. °dONLNd¨√ûœ⁄(κ If you show°dONLNd∏œ€Y(˜6the full page, °dONLNd«œY€⁄)ASa user can print on any device by putting the text in the correct location for that°dONLNd€Á:(6device.°dONLNd#ÛˇO*?Manufacturers of PostScript printers can add custom page sizes °dONLNdbÛOˇ⁄(mto the LaserWriter driver. If°dONLNdġ /('6they °dONLNdÖˇ/ ⁄)Ydo, the representation on the screen will be whatever they decide to define. Applications°dONLNdfl Ä(36Oshould not try to interpret custom page sizes. If your application ignores the °dONLNd. Ä⁄(3ûresults returned by°dONLNdB#(?63the driver, you risk incompatibility down the road.
  5960. °dONLNdv;JÜ*'3Asynchronous LaserWriter driver no longer supported
  5961. °dONLNd™JVÄ* Date Written:  9/24/91°dONLNd¡VbÅ* Last reviewed:  8/1/92°dONLNdÿnz?*What is °dONLNd‡n?z⁄)'Tcausing incorrect characters to be printed on the asynchronous LaserWriter driver we°dONLNd    5zÜz(¢6Ilicensed from Apple for use with a non-Apple PostScript-equipped printer?°dONLNd    Üí** ___ ¡4¡˘
  5962. *(12)
  5963.  of 21(÷|PR 510 - Printer Driver Q&As+(M.PR.PrtDvr.Q&Asˇ◊#ˇ ˇˇˇˇ#◊ 
  5964. IR,Times
  5965. .+Z-Developer Support Center(-€September 1993 /X/
  5966. °dONLNd)<5È(QZ%The printing of incorrect characters °dONLNd%)È5˛)≠7is probably due to an incompatibility between the async°dONLNd]5<A](]Z?driver and the version of PostScript being used in the printer.°dONLNdùM<Yô*The reason for the °dONLNd∞MôY˛)]Iincompatibility is that the driver is no longer supported and hasn’t been°dONLNd˙Y<e√(ÅZrevised for quite some time. °dONLNdY√e˛)á?The driver was originally developed outside of Apple, and Apple°dONLNdWe<qÀ(çZ!licensed the driver for its use. °dONLNdxeÀq˛)è<The company subsequently went out of business and the driver°dONLNdµq<}¥(ôZhasn’t been revved since.°dONLNdœâ<ï‡*!PostScript and Apple’s AppleTalk °dONLNdâ‡ï˛)§9LaserWriter drivers have been updated and changed quite a°dONLNd*ï<°æ(ΩZRbit since then, which is why the characters print correctly when using AppleTalk, °dONLNd|ïæ°˛(Ω‹ but not when°dONLNdâ°<≠&(…Z.printing asynchronously. The old async driver °dONLNd∑°&≠˛)Í'just doesn’t know how to handle the new°dONLNdfl≠<π_(’Z>PostScript versions and therefore prints “garbage” characters.°dONLNd≈<—g*?The SL Laser II driver is no longer supported by Apple, and at °dONLNd]≈g—˛(ÌÖthis time Apple has no plans to°dONLNd}—<›I(˘Z9update this driver or write a new one. Since things work °dONLNd∂—I›˛(˘g$correctly with AppleTalk, you should°dONLNd€›<È#(Z)confine usage to AppleTalk when printing °dONLNd›#È˛)Á)PostScript to the LaserWriter. If this is°dONLNd.È<ıê(ZCunacceptable, you might check around with different clearinghouses °dONLNdqÈêı˛(Æto see if a third-party°dONLNdâı<‰(ZXdeveloper has a compatible, up-to-date asynchronous LaserWriter driver that you can use.
  5967. °dONLNd‚<(Ë*'=Use LaserWriter driver srcCopy instead of srcOr transfer mode
  5968. °dONLNd (<4û* Date Written:  5/1/91°dONLNd64<@´* Last reviewed:  6/14/93°dONLNdNL<Xn*=I’m creating PICTs that are comprised of many lines drawn in °dONLNdãLnX˛(tåsrcOr mode. When using the°dONLNd¶X<d~(ÄZDLaserWriter 6.x or 7.x driver with the Color/Grayscale radio button °dONLNdÍX~d˛(Äúselected, some lines fail to°dONLNdd<p»(åZprint. Why is this happening?°dONLNd%p<|N* ___°dONLNd)à<î*SThe problem is a bug in the LaserWriter driver. Sometimes, when using a CGrafPort, °dONLNd|àî˛(∞the°dONLNdÄî<†(ºZNdriver doesn’t reproduce lines drawn in srcOr mode. (A CGrafPort is used when °dONLNdŒî†˛(ºthe°dONLNd“†<¨-(»Z3Color/Grayscale print option is selected; in Black °dONLNd†-¨˛)Ò)& White print mode, a regular grafPort is°dONLNd/¨<∏¡(‘Zused.) A workaround is to °dONLNdI¨¡∏˛)Ö;use srcCopy instead of srcOr when drawing QuickDraw objects°dONLNdÖ∏<ƒô(‡Zwithin your PICTs.
  5969. °dONLNdò‹<Ϊ*'7Save and restore long word if using $948 under System 7
  5970. °dONLNd–Î<˜§* Date Written:  6/11/91°dONLNdÁ˜<•* Last reviewed:  8/1/92°dONLNd˛<œ*UUnless my Macintosh application restores the contents of the long word at $948 after °dONLNdSœ˛(7Ì
  5971. using that°dONLNd^<'ñ(CZspace for globals, °dONLNdqñ'˛)ZHthe Finder draws icons incorrectly and my third-party LaserWriter driver°dONLNd∫'<3R(OZ7crashes. Is somebody now using $948 for other purposes?°dONLNdÚ3<?N* ___°dONLNdˆK<W≈*RThis is a known System 7 icon drawing bug, and also a bug with the printer driver °dONLNd    HK≈W˛(s„ that you are°dONLNd    UW<cZ(Zusing.°dONLNd    \o<{æ*VThe icon drawing utilities are trying to determine if a print page is currently open, °dONLNd    ≤oæ{˛(ó‹
  5972. by looking at°dONLNd    ¿{<á›(£Z]that variable ($948 is part of printvars). This turns out not to be such a good idea, and it °dONLNd
  5973. {›á˛(£˚will be°dONLNd
  5974. %á<ì(ØZ1fixed in the next release of the system software. ¡X¡
  5975. *'PR 510 - Printer Driver Q&As(÷˙13)
  5976.  of 21(ÏZM.PR.PrtDvr.Q&Asˇ.◊#ˇ ˇˇˇˇ#◊ 
  5977. IR,Times
  5978. .+6-Macintosh Technical Notes /4/˘
  5979. °dONLNd)5á*$The printer driver bug °dONLNd)á5⁄)oFthat you are experiencing is that every printer driver must return the°dONLNd^5A√(]6\variable at $948 to -1 when they are done printing. Also, while printing, the driver should °dONLNd∫5√A⁄(]·set it°dONLNd¡AMC(i6    to <> -1.
  5980. °dONLNdÀetº*';Update Backgrounder if using LaserWriter 7.0 under System 6
  5981. °dONLNdtÄÄ* Date Written:  7/10/91°dONLNdÄåÅ* Last reviewed:  8/1/92°dONLNd5ò§*3When we use the LaserWriter driver 7.0 with System °dONLNdhò§⁄)ˇ&6.0, the Chooser’s Background Printing°dONLNdè§∞â(Ã6KOn button is always dimmed. Is there any way to enable background printing?°dONLNd€∞º** ___°dONLNdfl»‘9*To get °dONLNdÊ»9‘⁄)!Sthe LaserWriter 7.0 driver to work with System 6.0.x, update your Backgrounder file°dONLNd:‘‡Ä(¸6Nwith the version on the Printing Tools disk that’s used to install System 7.0.°dONLNdâϯ¬*WIn short, to use the 7.0 LaserWriter Driver, 7.0 PrintMonitor, and System 6.0.x, place °dONLNd‡Ï¬¯⁄(‡these°dONLNdʯI( 6 files from °dONLNdÒ¯I⁄)1Sthe System 7.0 Printing Tools installation disks into your System Folder. All three°dONLNdE\(,6
  5982. must be used °dONLNdR\⁄)DOtogether for printing to work correctly. After you’ve placed these files in the°dONLNd¢Ø(86SSystem Folder, you should find the Background Printing option enabled for your use.°dONLNdˆ(4z*EThere are no known incompatibilities with the 7.0 drivers and System °dONLNd;(z4⁄(Pò6.0.x, so everyone°dONLNdN4@€(\6+should use the latest drivers, even with a °dONLNdy4€@⁄)√5mixed environment. This will also get rid of “printer°dONLNdØ@Lò(h6Pwars” that occur when users use more than one version of the LaserWriter driver °dONLNdˇ@òL⁄(h∂to print to the°dONLNdLXk(t6Lsame printer. (The printer must be reinitialized if the current user uses a °dONLNd[LkX⁄(tâdifferent version of the°dONLNdtXd„(Ä6,driver than that used by the previous user.)
  5983. °dONLNd°|ãL*',LaserPrep 7.0 file & AppleShare Print Server
  5984. °dONLNdŒãóÄ* Date Written:  7/15/91°dONLNdÂó£Å* Last reviewed:  8/1/92°dONLNd¸Øªv*The LaserPrep 7.0 °dONLNdØvª⁄)^Efile is included on the System 7 Printing disk and the System 7 Group°dONLNdTª«∫(„6SUpdate CD for upgrading the AppleShare Print Server to support the LaserWriter 7.0 °dONLNdߪ∫«⁄(„ÿdriver.°dONLNdØ«”Ø(Ô6XThe AppleShare Print Server has its own LaserWriter driver built in and all it needs to °dONLNd«Ø”⁄(ÔÕ
  5985. print is a°dONLNd”fl—(˚6(LaserPrep file. In fact, the AppleShare °dONLNd:”—fl⁄)π6Print Server completely ignores any LaserWriter driver°dONLNdqflÎÊ(6-installed in the System Folder of the server.°dONLNdü˜A*Page 49 °dONLNdߘAa))of the °dONLNdƘaˇ) System 7 Group Upgrade Guide°dONLNd ˜ˇ⁄)û- states the following procedure for upgrading°dONLNd¯n(+6Gan AppleShare Print Server to support the System 7 LaserWriter drivers:°dONLNd@'”*'1. Shut down the print server software.°dONLNdh'3¬* %2. Install the printer driver update…°dONLNdé3?Ã* $3. Drag the LaserPrep icon from the °dONLNd≤3Ã?⁄)¥7Printer Update folder to the Server Folder of the print°dONLNdÍ?Km(g6server Macintosh.°dONLNd¸KWè* O4. Restart the print server Macintosh and the AppleShare Print Server software.°dONLNd    Lcow*Actually, step #2 in °dONLNd    acwoâ)_the °dONLNd    ecâo')System 7 Group Upgrade Guide°dONLNd    Åc'o⁄)û' is unnecessary. Installing the printer°dONLNd    ©o{[(ó6Ddriver update has no effect on the AppleShare Print Server software. ¡4¡˘
  5986. *?14)
  5987.  of 21(÷|PR 510 - Printer Driver Q&As+(M.PR.PrtDvr.Q&Asˇ¨◊#ˇ ˇˇˇˇ#◊ 
  5988. IR,Times
  5989. .+Z-Developer Support Center(-€September 1993 /X/
  5990. °dONLNd<,Ö(HZ/LaserWriter 7.0 driver and LaserPrep dictionary
  5991. °dONLNd0,<8§* Date Written:  8/29/91°dONLNdG8<D´* Last reviewed:  6/14/93°dONLNd_P<\*/In the old LaserWriter drivers it was possible °dONLNdéP\˛)‡/to create a PostScript file with or without the°dONLNdæ\<h(ÑZ-LaserPrep dictionary (“f” or “k” key). Is it °dONLNdÎ\h˛)”2possible to generate a file without the dictionary°dONLNdh<t‘(êZ with the LaserWriter 7.0 driver?°dONLNd?t<ÄN* ___°dONLNdCå<ò$*2In 7.0 printing, a LaserPrep dictionary is always °dONLNduå$ò˛)Ë.sent with a print job. This is done to prevent°dONLNd§ò<§(¿Z-constant reinitialization of the LaserWriter °dONLNd—ò§˛)»5by conflicting printer drivers. You cannot prevent it°dONLNd§<∞ˆ(ÃZ%from being sent. Fortunately the 7.0 °dONLNd,§ˆ∞˛)∫3version of the LaserPrep dictionary is much smaller°dONLNd`∞<ºÛ(ÿZ'(≈40K total) than its 6.x predecessors.
  5992. °dONLNdà‘<„„*'<LaserWriter ignores ForeColor while filling smoothed polygon
  5993. °dONLNd≈„<Ô§* Date Written:  10/8/91°dONLNd‹Ô<˚•* Last reviewed:  8/1/92°dONLNdÛ<}*BWhen doing the FillRgn for drawing the fill of a smoothed polygon °dONLNd5}˛(/õ(as described in Macintosh°dONLNdP<ÿ(;ZTTech Note #91) the foreColor isn’t used on the LaserWriter. Any way to make it work?°dONLNd•<+N* ___°dONLNd©7<C*AYou’ve discovered a design limitation of the LaserWriter driver. °dONLNdÍ7C˛(_ùThings that have patterns°dONLNdC<O™(kZMassociated with them are rendered by using the LaserWriter screen operators. °dONLNdQC™O˛(k»This results in an°dONLNddO<[À(wZassumption of the foreground °dONLNdÅOÀ[˛)è=color being black and the background color being white, which°dONLNdø[<gJ(ÉZis °dONLNd¬[Jg˛)Qwhat’s causing the problem you noticed. In short, it makes the driver ignore your°dONLNdg<s‰(èZ!foreground and background colors.°dONLNd6<ãS*1You can work around the problem by working in an °dONLNdgSã˛(ßq off-screen GWorld first and then°dONLNdàã<óà(≥ZFCopyBitsing everything to the printer port using srcCopy. There are a °dONLNdŒãàó˛(≥¶couple of problems with°dONLNdÊó<£–(øZZthis approach: First, don’t do it with text or your text will be turned into a bitmap and °dONLNd@󖣞(øÓ
  5994. you’ll get°dONLNdK£<Ø^(ÀZ<the “jaggies.” Second, you’ll probably want to increase the °dONLNdá£^Ø˛(À|"printer port’s resolution from its°dONLNd™Ø<ª(◊Z1default of 72 dpi for better results. A value of °dONLNd€Øª˛)Ÿ0288 dpi works nicely since it’s an even multiple°dONLNd ª<«(„Z)of QuickDraw’s native 72-dpi resolution. °dONLNd5ª«˛)Δ2Also, make sure that the GWorld you create has the°dONLNdh«<”ò(ÔZGsame bounds as the printer port’s rPage rectangle to avoid unnecessary °dONLNdØ«ò”˛(Ô∂scaling and clipping.°dONLNd≈”<flT(˚Z:After you’ve done all that, draw into it and CopyBits the °dONLNdˇ”Tfl˛(˚r$result to the printer port. The nice°dONLNd$fl<Î˙(Z(thing about doing everything off-screen °dONLNdLfl˙Î˙)æ6first is that then you can use some of the non-printer°dONLNdÇfl˙β(-°dONLNdÉÎ<˜p(ZBfriendly transfer modes like blend or dithered. Also, you can use °dONLNd≈Îp˜˛(éForeColor/BackColor and get°dONLNd·˜<≠(Zthe right thing this way.°dONLNd˚<p*EIf you don’t want to use this method for all printers, (since it can °dONLNd    @p˛(7ébe quite a memory hog), you°dONLNd    \<'º(CZPcan check for the LaserWriter driver and use this method in just that case. For °dONLNd    ¨º'˛(C⁄other drivers,°dONLNd    ª'<3”(OZ you should just print as normal.°dONLNd    ‹?<K–*So, what do you need to do °dONLNd    ˜?–K˛)î>all this? Well, to set the resolution of the printer port, use°dONLNd
  5995. 6K<W∏(sZPrGeneral as described in °dONLNd
  5996. PK∏W    )|Inside Macintosh°dONLNd
  5997. `K    WS)Q Volume V and °dONLNd
  5998. nKSWx)Jdevelop°dONLNd
  5999. uKxWã)% #3.°dONLNd
  6000. zc<oë(ãZGTo determine whether you have the LaserWriter driver or not, check the °dONLNd
  6001. ¡cëo˛(ãØhigh byte of the wDev°dONLNd
  6002. ◊o<{Ë(óZ!field in your print handle. This °dONLNd
  6003. ¯oË{˛)¨1is described in the Tech Note “Optimizing For The°dONLNd *{<á>(£Z1LaserWriter—Techniques.” While this method might °dONLNd [{>á˛(£\'break some day, it’s currently the best ¡X¡
  6004. (÷ZPR 510 - Printer Driver Q&As(÷˙15)
  6005.  of 21(ÏZM.PR.PrtDvr.Q&Asˇ◊#ˇ ˇˇˇˇ#◊ 
  6006. IR,Times
  6007. .+6-Macintosh Technical Notes /4/˘
  6008. °dONLNd)J*;way to determine which driver you’re using, and Apple will °dONLNd;J)⁄(Ehhave to let developers know°dONLNdW)5q(Q6before we break it.°dONLNdkAMc*If the high byte °dONLNd|AcM⁄)KNof the wDev is 3, then you either have the LaserWriter driver or a third-party°dONLNdÀMYb(u6Adriver impersonating the LaserWriter. Some PostScript drivers do °dONLNd MbY⁄(uÄthat because many apps°dONLNd#YeH(Å6    assume a °dONLNd,YHe⁄)0OwDev of 3 means a PostScript printer, and anything else doesn’t. By acting like°dONLNd|eq°(ç6Apple’s LaserWriter driver, °dONLNdòe°q⁄)âAthey get preferential treatment from apps that “special case” for°dONLNd⁄q}(ô6:PostScript. That’s not really a problem in this situation.
  6009. °dONLNdï§ø*'<LaserWriter driver PostScript error strings & document names
  6010. °dONLNdR§∞Ü* Date Written:  12/11/91°dONLNdj∞ºÅ* Last reviewed:  8/1/92°dONLNdÅ»‘w*LI discovered an interesting bug in the Macintosh LaserWriter driver. If the °dONLNdÕ»w‘⁄(ïword “timeout” is in°dONLNd‚‘‡√(¸6Tthe name of a document, the LaserWriter driver will give a timeout error -8132. Are °dONLNd6‘√‡⁄(¸·there°dONLNd<‡Ï}(6similar magic words?°dONLNdQϯ** ___°dONLNdUö*NPostScript error messages are sent from the LaserWriter to the driver as text °dONLNd£ö⁄(,∏ streams. The°dONLNd∞h(86Idriver must check these strings to see if they contain an error message. °dONLNd˘h⁄(8ÜIf a document is named°dONLNd(Ë(D6+something that contains the same string as °dONLNd;Ë(⁄)–0a PostScript error message, the driver may think°dONLNdl(4Æ(P6Nthere’s an error when the printer sends the “status: printing document XXXXX” °dONLNd∫(Æ4⁄(PÃmessage.°dONLNd√4@(\62Other strings cause similar problems; one of them °dONLNdı4@⁄)Ì-is “printer out of paper.” If you want to see°dONLNd#@L∏(h6%the rest of the strings, take a look °dONLNdH@∏L⁄)†;at the LaserWriter printer driver resource type 'PREC' ID =°dONLNdÑLX.(t6109.
  6011. °dONLNdâpz*'2Personal LaserWriter NTR has longer product string
  6012. °dONLNdºãÄ* Date Written:  3/17/92°dONLNd”ãóá* Last reviewed:  6/14/93°dONLNdΣØ*The following line of °dONLNd£Ø⁄)gEmy PostScript code causes the Personal LaserWriter NTR to gag, but it°dONLNdGتG(◊6?has worked with all other Apple LaserWriter printers up to now:,
  6013. Courier
  6014.     °dONLNdá«“û*N  statusdict/product get str cvs show  % Gets & prints the name of the printer
  6015. °dONLNd÷›ÈÖ*where str is defined as:
  6016.     °dONLNdÔı|*  /str 20 string def
  6017. °dONLNdˇ ** ___°dONLNd#*,The product name stored for this printer is °dONLNd4#⁄)Í'(LaserWriter Personal NTR) or (Personal°dONLNd\#/v(K6LaserWriter NTR), °dONLNdn#v/⁄)^Idepending on whether you’re using statusdict or systemdict, respectively.°dONLNd∏/;…(W6(In either case, the product’s length is °dONLNd‡/…;⁄)±924 characters. Since you’re only allocating 20 characters°dONLNd;G≥(c6Xfor the 2nd string you use with cvs, you’re getting a rangecheck error. Changing str to:
  6018.     °dONLNdsS^|*  /str 24 string def
  6019. °dONLNdàiu.*3fixes the problem. You may want to make the string °dONLNdªi.u⁄(ëL!even larger than 24 characters to°dONLNd›uÅ(ù6/accommodate longer product names in the future. ¡4¡˘
  6020. *916)
  6021.  of 21(÷|PR 510 - Printer Driver Q&As+(M.PR.PrtDvr.Q&Asˇ◊#ˇ ˇˇˇˇ#◊ 
  6022. IR,Times
  6023. .+Z-Developer Support Center(-€September 1993 /X/
  6024. °dONLNd<)Í(EZUAssumptions about the length of PostScript product strings are a common problem with °dONLNdUÍ)˛(Enew°dONLNdY)<5à(QZCprinters (having more verbose names). In fact, you should have the °dONLNdú)à5˛(Q¶same trouble if you run°dONLNd¥5<A‚(]ZWyour original PostScript on the Personal LaserWriter NT, which has a 23 character name.
  6025. °dONLNd Y<h]*'*LaserWriter II SC fonts and 4x bitmap size
  6026. °dONLNd7h<t™* Date Written:  11/17/89°dONLNdOt<Ä´* Last reviewed:  6/14/93°dONLNdgå<òœ*Why do I need to have four °dONLNdÇåœò˛)ì;times the bitmap size of the font I want to print in on the°dONLNdæò<§ñ(¿ZLaserWriter II SC?°dONLNd—§<∞N* ___°dONLNd’º<»Ç*LaserWriter II °dONLNd‰ºÇ»˛)FOSC fonts are four times the point size of the associated Macintosh screen font.°dONLNd4»<‘(Z+The pixels on the screen are four times as °dONLNd_»‘˛)Δ7far apart (center to center) as the dots printed by the°dONLNdó‘<‡·(¸ZXLaserWriter SC. When the bitmaps for one of the printer fonts is printed, the result is °dONLNdÔ‘·‡˛(¸ˇa font°dONLNdˆ‡<Ï(Z2with a resolution four times greater than that of °dONLNd(‡Ï˛)‡2the font displayed, but at a size identical to the°dONLNd[Ï<¯ƒ(Zfont displayed on the screen.
  6027. °dONLNdy<J*''Font families shipped with LaserWriters
  6028. °dONLNd°<+™* Date Written:  11/17/89°dONLNdπ+<7•* Last reviewed:  8/1/92°dONLNd–C<Oä*What fonts and °dONLNdflCäO∞)N;sizes are shipped with the LaserWriter Plus, LaserWriter II
  6029. °dONLNdC∞OΩ(kŒNT
  6030. °dONLNdCΩO˛)
  6031.  
  6032. , LaserWriter°dONLNd*O<[D(wZII
  6033. °dONLNd,OD[X)NTX
  6034. °dONLNd/OX[¬), and LaserWriter SC?°dONLNdE[<gN(ÉZ___°dONLNdIs<Ô*$The LaserWriter Plus, LaserWriter II
  6035. °dONLNdmsÔ¸)≥NT
  6036. °dONLNdos¸)
  6037. , °dONLNdqs_)and LaserWriter II
  6038. °dONLNdÉs_s)[NTX
  6039. °dONLNdÜss˛), shipped with a total of 11°dONLNd£<ã
  6040. (ßZ-font families with the sizes indicated below:°dONLNd—ó<£N*8Times, Helvetica, Courier, Symbol: 9, 10, 12, 14, 18, 24°dONLNd
  6041. Ø<ª *(Palatino, Helvetica Narrow, ITC Bookman,°dONLNd3ª<«* *ITC Avant Garde Gothic, ITC Zapf Chancery,°dONLNd^«<”s* <ITC Zapf Dingbats, New Century Schoolbook 10, 12, 14, 18, 24°dONLNdõfl<Îı*]A total of four font families are shipped with the SC: Courier, Symbol, Times, and Helvetica °dONLNd¯flıβ(in°dONLNd˚Î<˜P(Z;the following sizes: 9, 10, 12, 14, 18, 24, 36, 48, 56, 72,°dONLNd7˜<L* 96.
  6042. °dONLNd;<*ÿ*';Disable Graphics Smoothing for printing large bitmap images
  6043. °dONLNdw*<6û* Date Written:  5/3/89°dONLNdç6<B´* Last reviewed:  6/14/93°dONLNd•N<ZÈ*TWhen printing large (possibly scanned) Macintosh bitmap images, the page is printed °dONLNd˘NÈZ˛(vwith°dONLNd˛Z<fL(ÇZ8small lines running horizontally through the image. Why?°dONLNd7f<rN* ___°dONLNd;~<äÊ*VIn System 6.0 the QuickDraw DrawPicture call was revised to fix some problems. One of °dONLNdë~Êä˛(¶these°dONLNdóä<ñó(≤ZGproblems concerned large bitmaps. To help solve the problem of bitmaps °dONLNdfiäóñ˛(≤µthat were too large to ¡X¡
  6044. (÷ZPR 510 - Printer Driver Q&As(÷˙17)
  6045.  of 21(ÏZM.PR.PrtDvr.Q&Asˇr◊#ˇ ˇˇˇˇ#◊ 
  6046. IR,Times
  6047. .+6-Macintosh Technical Notes /4/˘
  6048. °dONLNd)Ö*Gbe printed, DrawPicture was modified to “band” the CopyBits request if °dONLNdGÖ)⁄(E£it was too large.°dONLNdY)5
  6049. (Q64Banding is the process of converting a large bitmap °dONLNdç)
  6050. 5⁄)ı*into several smaller bitmaps. This banding°dONLNd∏5Aç(]6usually occurs vertically °dONLNd“5çA⁄)uAdown the page. When DrawPicture bands a large bitmap into pieces,°dONLNdAMV(i6Dthe smoothing algorithm of the LaserWriter is applied to each piece °dONLNdXAVM⁄(itseparately, instead of being°dONLNduMY=(u6applied °dONLNd}M=Y⁄)%Sto the entire bitmap at once. Since the process of smoothing involves removing some°dONLNd—Yej(Å6Bpixels, hairlines will be created between the bitmap bands. There °dONLNdYje⁄(Åàis no way to tell the°dONLNd)eqz(ç6NLaserWriter driver that the smaller bitmaps are all part of one large bitmap, °dONLNdwezq⁄(çòso the only solution°dONLNdåq}©(ô6Sto this problem is to disable Graphics Smoothing when printing large bitmap images.
  6051. °dONLNd‡ï§q*'0Difference between LaserWriter 7.0 and 7.1 Namer
  6052. °dONLNd§∞z* Date Written:  3/3/92°dONLNd'∞ºÅ* Last reviewed:  8/1/92°dONLNd>»‘*-Apple Software Licensing’s “Exhibit C” lists °dONLNdk»‘⁄)Ô'localized Namer 7.0 versions in several°dONLNd쑇Δ(¸6\languages, and mentions that these localized versions of the Namer are available in version °dONLNdÔ‘Δ‡⁄(¸‰7.1.°dONLNdÙ‡Ï((68What is the difference in the Namer between 7.0 and 7.1?°dONLNd-ϯ** ___°dONLNd1G*    The main °dONLNd:G⁄)/Tdifference between the LaserWriter utility 7.0 and 7.1 is that part of the Namer has°dONLNdè;(86@been integrated into the 7.1 version of the software. Until the °dONLNdœ;⁄(8Y LaserWriter utility 7.1 was made°dONLNd(í(D6available, the Namer was °dONLNd    í(⁄)zDa stand-alone application. However, the LaserWriter utility does not°dONLNdN(4'(P6do °dONLNdQ('4⁄)Severything the Namer does. For example, the Namer renames AppleTalked ImageWriters,°dONLNd•4@î(\6Sbut the LaserWriter utility doesn’t. For all your printer configuration needs, you °dONLNd¯4î@⁄(\≤should use the°dONLNd@Lú(h67.1 version of the software.
  6053. °dONLNd$dsé*'6ImageWriter and printing multiple copies in draft mode
  6054. °dONLNd[sz* Date Written:  1/6/92°dONLNdqãá* Last reviewed:  6/14/93°dONLNdâó£-*Our °dONLNdçó-£⁄)Yapplication can’t print multiple copies on the ImageWriter in Draft mode. If we type in 3°dONLNdÁ£Ø≥(À6!copies in the ImageWriter driver °dONLNd£≥Ø⁄)õ:dialog box in Draft mode, we only get one copy. Everything°dONLNdCت{(◊6Mprints fine in Best or Faster modes. Is this a bug in the ImageWriter driver?°dONLNd몫** ___°dONLNdï”flÃ*^Although it seems like this must be a bug in the ImageWriter driver, it’s not. In Draft mode, °dONLNdÛ”Ãfl⁄(˚Íthe°dONLNd˜flÎ+(68application that’s printing must make sure the required °dONLNd/fl+Î⁄(I!number of pages are printed. This°dONLNdQΘq(6Jinvolves cycling through the app’s print loop for each copy to be printed.°dONLNdúÃ*]In Draft mode on an ImageWriter, nothing is spooled to disk; the data is immediately sent to °dONLNd˘Ã⁄(+Íthe°dONLNd˝è(76Rprinter. Therefore, the data is no longer available once it’s sent to the printer °dONLNd    Oè⁄(7≠(and there’s no°dONLNd    _'@(C6way for °dONLNd    g@'⁄)(Vthe print driver to resend it for multiple copies). When the ImageWriter spool-prints,°dONLNd    æ'3`(O6Ithe file that’s created is printed the required number of times for you. °dONLNd
  6055. '`3⁄(O~Therefore, your app only°dONLNd
  6056.  3?8([6<needs to handle multiple copies when printing in Draft mode.°dONLNd
  6057. ]KW¥*Here’s what your app should do:°dONLNd
  6058. }co≥*!1. Validate the print record and °dONLNd
  6059. ûc≥o⁄)õ:present the job dialog. This allows the user to choose how°dONLNd
  6060. Ÿo{y(ó6Nmany copies to print and allows the printer driver to adjust the print record °dONLNd 'oy{⁄(óóto reflect how many°dONLNd ;{á∂(£6!copies your program has to print. ¡4¡˘
  6061. *318)
  6062.  of 21(÷|PR 510 - Printer Driver Q&As+(M.PR.PrtDvr.Q&AsˇD◊#ˇ ˇˇˇˇ#◊ 
  6063. IR,Times
  6064. .+Z-Developer Support Center(-€September 1993 /X/
  6065. °dONLNd<)º(EZR2. Get the number of copies that you’re expected to handle from the print record. °dONLNdRº)˛(E⁄In the case of°dONLNda)<5(QZ_spool printing, this number will be set to 1 (since the multiple copies are handled for you by °dONLNd¿)5˛(Qthe°dONLNdƒ5<A…(]ZWprinter driver). In any case, the following Pascal code will give you the correct info.,
  6066. Courier
  6067.     °dONLNdM<Xê*D    numCopies:= printHdl^^.prJob.iCopies;  (* From IM 2, pg. 151. *)
  6068. °dONLNdac<oË*P3. For each copy in numCopies, loop through the PrOpenDoc/PrCloseDoc section of °dONLNd±cËo˛(ãyour°dONLNd∂o<{V(óZcode.°dONLNdºá<ì§*GThis method is demonstrated in the code for the Macintosh Tech Note “A °dONLNdá§ì˛(جPrinting Loop that°dONLNdì<ü(ªZ,Cares…,” which describes a model print loop.
  6069. °dONLNdC∑<Δ˚*'Dogcow logo is trademarked
  6070. °dONLNd^Δ<“§* Date Written:  9/10/92°dONLNdu“<fi´* Last reviewed:  6/14/93°dONLNdçÍ<ˆñ*HWe would like to use the “dogcow” icon in our Page Setup dialog. Is the °dONLNd’Íñˆ˛(¥dogcow trademarked,°dONLNdȈ<j(ZBand are there any restrictions on using this icon in our software?°dONLNd,<N* ___°dONLNd0<&•*LYes, the dogcow logo (along with its call, “Moof!”) is a trademark of Apple °dONLNd|•&˛(B√and is proprietary.°dONLNdê&<2°(NZThe dogcow appears °dONLNd£&°2⁄)e on Apple’s °dONLNdÆ&⁄2?)9Developer CD Series°dONLNd¡&?2˛)e( disc and in other material. Apple has a°dONLNdÍ2<>∏(ZZpending U.S. registration °dONLNd2∏>˛)|Fon it. Accordingly, it’s not available to third-party developers as an°dONLNdK><Jô(fZicon or file symbol.
  6071. °dONLNd`b<qr*'.“Printer driver is MultiFinder compatible” bit
  6072. °dONLNdèq<}§* Date Written:  7/29/92°dONLNd¶}<â´* Last reviewed:  6/14/93°dONLNdæï<°À*VCould you tell me what the “printer driver is MultiFinder compatible” bit is used for?°dONLNd°<≠N* ___°dONLNdπ<≈*/The “printer driver is MultiFinder compatible” °dONLNdHπ≈˛)‚/bit provides two features. First, it allows the°dONLNdx≈<—_(ÌZprinter °dONLNdÄ≈_—˛)#Sdriver resource file to be opened by multiple clients. This was obviously needed to°dONLNd‘—<›Õ(˘Zsupport multiple applications °dONLNdÚ—Õ›˛)ë<printing simultaneously under MultiFinder. The other feature°dONLNd/›<ÈÀ(ZRprovided by the flag is the loading of PDEFs into the system heap rather than the °dONLNdÅ›ÀÈ˛(È application°dONLNdçÈ<ı (Z/heap (which is where they go under the Finder).°dONLNdΩ<
  6073. Ï*YThe MultiFinder-compatible bit has a major limitation: If your driver has this flag set, °dONLNdÏ
  6074. ˛()
  6075. you°dONLNd
  6076. <Ã(5ZParen’t allowed to add or resize resources, or do anything else that would cause °dONLNdj
  6077. Ã˙(5Íthe RAM°dONLNdq
  6078. ˙˛).-°dONLNdr<%(AZ*resident resource map to change. Although °dONLNdú%˛)Ÿ/MultiFinder lets multiple applications open the°dONLNdÃ%<1õ(MZprinter resource file °dONLNd‚%õ1˛)_Jat the same time, it has no control over the resource map that gets loaded°dONLNd-1<=4(YZ1by the Resource Manager when the file is opened. °dONLNd^14=˛)¯)Because of this, each client gets its own°dONLNdà=<Iè(eZDpersonal copy of the resource map. When these clients get done with °dONLNdÃ=èI˛(e≠the file, they write the°dONLNdÂI<U(qZEresource map back to the file (via UpdateResFile). Obviously, if the °dONLNd    *IU˛(qùresources have changed in°dONLNd    DU<a(}Z/any way, the last client to call UpdateResFile °dONLNd    sUa˛)◊/is the only one whose changes will be recorded.°dONLNd    £a<m´(âZThis is a “thrill seeker” °dONLNd    Ωa´m˛)oGmethod of handling the printer driver resource files, but since none of°dONLNd
  6079. m<yï(ïZKthe Apple printer drivers currently add or resize resources, it made sense. ¡X¡
  6080. *APR 510 - Printer Driver Q&As(÷˙19)
  6081.  of 21(ÏZM.PR.PrtDvr.Q&AsˇB◊#ˇ ˇˇˇˇ#◊ 
  6082. IR,Times
  6083. .+6-Macintosh Technical Notes /4/˘
  6084. °dONLNd)6*<So the bottom line here is that if you want your drivers to °dONLNd<6)⁄(ET be compatible under MultiFinder,°dONLNd])5®(Q6Uyou’ll have to implement a scheme that doesn’t require adding or resizing resources. °dONLNd≤)®5⁄(QΔ
  6085. It’s OK to°dONLNdΩ5A¶(]6Rchange the data in a resource, as long as you don’t change its size. Changing the °dONLNd5¶A⁄(]ƒ
  6086. data won’t°dONLNdAM≈(i6]cause changes to the resource map, so each client will still have accurate copies of the map.°dONLNdxYeX*BHere’s what would happen to your printer driver’s resources under °dONLNd∫YXe⁄(Åvthe Finder and MultiFinder°dONLNd’eq‚(ç6+when the MultiFinder-compatible bit is set:°dONLNd}âD*9• Under the Finder in system software version 6.0.x: All °dONLNd:}Dâ⁄(•bresources are loaded into the°dONLNdXâïo(±6Lapplication heap—regardless of the resource attribute’s bit setting. If the °dONLNd§âoï⁄(±çresource has the “load°dONLNdªï°b(Ω6into the system °dONLNdÀïb°⁄)JRheap” bit set, it will still be loaded into the application heap under the Finder.°dONLNd°≠1(…6This °dONLNd#°1≠⁄)Smakes sense in the Finder world because the application heap will usually have more°dONLNdw≠πö(’6room than the system heap.°dONLNdí≈—ı*-• Under MultiFinder in System 6 or System 7: °dONLNdø≈ı—⁄)›1All the printer driver’s resources will be loaded°dONLNdÒ—›ø(˘6]into the system heap. This is true whether the “load into the system heap” bit is set or not.°dONLNdOÈıt*GWhy does the resource loading occur this way, even when the resource’s °dONLNdñÈtı⁄(í“load into the system°dONLNd¨ı∂(6[heap” bit is set? Patches to the GetResource trap load all your printer driver’s resources °dONLNdı∂⁄(‘into the°dONLNd
  6087. X()6=system heap when the MultiFinder-compatible bit is set under °dONLNdMX
  6088. ⁄()vMultiFinder, and into the°dONLNdg
  6089. N(56 application °dONLNds
  6090. N⁄)6Pheap under the Finder (as described above), which is why you can’t override this°dONLNdƒ%E(A6    behavior.°dONLNdŒ1=Ã*PBy the way, you should be aware of the SetPDiMC MPW tool, which is available on °dONLNd1Ã=⁄(YÍthe°dONLNd"=I{(e6Developer CD Series°dONLNd5={I¿)cH disc. It will automatically set the MultiFinder-compatible bit for you °dONLNd}=¿I⁄(efiwhen°dONLNdÇIU£(q6you build your printer driver.
  6091. °dONLNd°m||*'6Use FillCRect off-screen, not directly to printer port
  6092. °dONLNdÿ|àÄ* Date Written:  8/25/92°dONLNdÔàîç* Last reviewed:  11/30/92°dONLNd†¨Ã*YWe’re having problems with color patterns using the LaserWriter driver version 7.1.2. If °dONLNda†Ã¨⁄(»Íwe°dONLNdd¨∏æ(‘6Ycreate a 'ppat' resource in ResEdit (32 x 32 bits, in this case) and then do a FillCRect °dONLNdΩ¨æ∏⁄(‘‹to the°dONLNdƒ∏ƒ(‡68port returned by PrOpenDoc (with color set so that it’s °dONLNd¸∏ƒ⁄(‡:'a cGrafPort) with the pattern loaded by°dONLNd$ƒ–®(Ï6JGetPixPat, we get a weird pattern. Doing the same to an off-screen GWorld °dONLNdnƒ®–⁄(ÏΔ    and using°dONLNdx–‹H(¯6    CopyBits °dONLNdÅ–H‹⁄)0Tto copy to the printer port works fine, if a little slowly. Are we missing something°dONLNd÷‹Ë1(6here?°dONLNd‹ËÙ** ___°dONLNd‡ -*:You need to use the FillCRect call off-screen rather than °dONLNd    - ⁄((K&directly into the printer port, for at°dONLNd    A ˇ(461least two reasons. First, the LaserWriter driver °dONLNd    r ˇ⁄)Á-doesn’t support filling objects with anything°dONLNd    †$É(@6Lbut black-and-white patterns because it uses the PostScript halftone screen °dONLNd    ÏÉ$⁄(@°functions to draw°dONLNd    ˛$0Ç(L6patterns. Second, the °dONLNd
  6093. $Ç0⁄)jELaserWriter driver doesn’t understand (or handle) pixPats. Therefore,°dONLNd
  6094. Z0<(X6your only recourse is °dONLNd
  6095. p0<⁄)gBthe one you discovered—to copy to and from GWorlds. Unfortunately,°dONLNd
  6096. ≥<HÙ(d6,FillCRect doesn’t work with the LaserWriter °dONLNd
  6097. fl<ÙH⁄)‹.drivers through version 7.2. After version 7.2°dONLNd HTπ(p6!this probably won’t be a problem.
  6098. °dONLNd 0l{∑*'9Color/Grayscale button on a non–Color QuickDraw Macintosh
  6099. °dONLNd j{áÄ* Date Written:  8/31/92°dONLNd Åáìá* Last reviewed:  6/14/93 ¡4¡˘
  6100. *'20)
  6101.  of 21(÷|PR 510 - Printer Driver Q&As+(M.PR.PrtDvr.Q&AsˇÍ◊#ˇ ˇˇˇˇ#◊ 
  6102. IR,Times
  6103. .+Z-Developer Support Center(-€September 1993 /X/
  6104. °dONLNd)<5»(QZOThe LaserWriter driver displays the Color/Grayscale option even on a non–Color °dONLNdO)»5˛(QÊ    QuickDraw°dONLNdY5<Ah(]Z7Macintosh, which seems odd because the option normally °dONLNdê5hA˛(]Ücauses the driver to return a°dONLNdÆA<Mø(iZHCGrafPort to the calling application, and CGrafPorts are only available °dONLNdˆAøM˛(i› under Color°dONLNdM<Y(uZ+QuickDraw. What happens if you’re printing °dONLNd-MY˛)◊/original QuickDraw colors using the LaserWriter°dONLNd]Y<eô(ÅZEdriver on a non–Color QuickDraw system? Does the driver just use the °dONLNd¢Yôe˛(Å∑Black & White code°dONLNdµe<q\(çZ=regardless of whether the Color/Grayscale button is selected?°dONLNdÛq<}N* ___°dONLNd˜â<ï`*>Regardless of whether Color/Grayscale is selected or not, the °dONLNd5â`ï˛(±~!driver returns a grafPort because°dONLNdWï<°ó(ΩZit’s not running on °dONLNdkïó°˛)[Ga Color QuickDraw machine. But, if the Color/Grayscale option is chosen°dONLNd≥°<≠(…Z,on a Macintosh without Color QuickDraw, the °dONLNdfl°≠˛)fi.driver doesn’t just use the Black & White code°dONLNd≠<πd(’ZEto print. Instead, it sends the colors to the printer as best it can °dONLNdS≠dπ˛(’Çwithout Color QuickDraw. This°dONLNdqπ<≈¿(·ZTcan result in three different sets of output when printing classic QuickDraw colors:°dONLNdΔ—<›’* • Black & White button selected °dONLNdÊ—’›˛)ô;(identical output whether the system has Color QuickDraw or°dONLNd"›<ÈO(Znot)°dONLNd'È<ıs* >• Color/Grayscale button selected on Color QuickDraw Macintosh°dONLNdfı<â* B• Color/Grayscale button selected on non-Color QuickDraw Macintosh ¡X¡
  6105. (÷ZPR 510 - Printer Driver Q&As(÷˙21)
  6106.  of 21(ÏZM.PR.PrtDvr.Q&Asˇb◊#ˇ ˇˇˇˇ#◊†Ç 
  6107. /ZÅ#
  6108.     0Ià:µú9"{    ˇˇˇˇˇˇˇˇ#†ƒ°d
  6109. ONLNf˛†å°d1drw2…-·_ġˇˇˇˇˇè°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˙ó@†ò,Times
  6110. .R…R…+]BNew Technical Notes†ô°ddrw2:°„†ó°d1drw2eÙġˇˇˇˇˇP°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚ÄE¿†ò
  6111. ({ïDeveloper Support†ô°ddrw2:°„†ó°d`drw2-ÔˇˇˇˇˇˇKÔ- Z  ffZ°d1drw2 ¿˙ÈˇˇˇˇˇˇK°ñ x°ddrw2:°ddrw2:$°d4drw2:0°öˇÙĆò
  6112. 0(UÔ†ô°ddrw2:°„†ó°d1drw2ÔÊ˙ˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:    °öˇ˝Ä†ò
  6113.     +&    ®†ô°ddrw2:°„†ó°d1drw2Â-¯yˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚Ä%†ò
  6114. (Z\    Macintosh†ô°ddrw2:°„†ó†ç°ddrw2D†É
  6115. IR.°dONLNdn<ÅS(õZPR 515 - Printing Manager Q&As
  6116. °dONLNdÄ<ès*Printing
  6117. °dONLNd)õ<ßt* Revised by:°dONLNd5õÑߡ)HDeveloper Support Center°dONLNdNõ±ß˛(√œSeptember 1993°dONLNd]ß<≥q(œZ Written by:°dONLNdißÑ≥ˇ)HDeveloper Support Center°dONLNdÇßæ≥˛(œ‹ October 1990°dONLNdèø<À⁄(ÁZThis Technical Note contains a °dONLNdÆø⁄À˛)û9collection of Q&As relating to a specific topic—questions°dONLNdËÀ<◊†(ÛZGyou’ve sent the Developer Support Center (DSC) along with answers from °dONLNd/À†◊˛(Ûæthe DSC engineers.°dONLNdB◊<„u(ˇZ
  6118. While DSC °dONLNdL◊u„˛)9Lengineers have checked the Q&A content for accuracy, the Q&A Technical Notes°dONLNdô„<Ôq( Z don’t have °dONLNd§„qÔ˛)5Qthe editing and organization of other Technical Notes. The Q&A function is to get°dONLNdˆÔ<˚Ÿ(Znew technical information and °dONLNdÔŸ˚˛)ù6updates to you quickly, saving the polish for when the°dONLNdK˚<(#Z,information migrates into reference manuals.°dONLNdx<k*:Q&As are now included with Technical Notes to make access °dONLNd≤k˛(;âto technical updates easier for°dONLNd“<+.(GZ/you. If you have comments or suggestions about °dONLNd.+˛)Ú*Q&A content or distribution, please let us°dONLNd,+<7\(SZknow °dONLNd1+\7˛) Iby sending an AppleLink to DEVFEEDBACK. Apple Partners may send technical°dONLNd{7<Ci(_Z9questions about Q&A content to DEVSUPPORT for resolution.°dONLNdµO<[·* New Q&As in this Technical Note:°dONLNd÷[<gG* 5OK to call WaitNextEvent if modal window is frontmost íXí
  6119. °dONLNd å<õµ*45OK to call WaitNextEvent if modal window is frontmost
  6120. °dONLNdBõ<ß§* Date Written:  1/20/93°dONLNdYß<≥´* Last reviewed:  6/14/93°dONLNdqø<À∂*QI’ve read in “Print Hints: Top 10 Printing Crimes” that a program shouldn’t call °dONLNd¬ø∂À˛(Á‘
  6121. WaitNextEvent°dONLNd–À<◊Ñ(ÛZwhile the Print °dONLNd‡ÀÑ◊˛)HKManager is open, but I call WaitNextEvent in my pIdleProc so my application°dONLNd,◊<„O(ˇZ;can detect a user cancellation. Could this cause a problem?°dONLNdh„<ÔN* ___°dONLNdl˚<’*The reason you shouldn’t call °dONLNdä˚’˛)ô8WaitNextEvent is to prevent the system from switching to°dONLNd√<’(/Z!another application. If you have °dONLNd‰’˛)ô;a modal dialog-type window in front (the one with the modal°dONLNd <k(;Zwindow °dONLNd'k˛)/Iproc ID), the system will never switch applications and it’s safe to call°dONLNdq<+4(GZ4WaitNextEvent. This is why all Apple’s drivers that °dONLNd•4+˛)¯(call WaitNextEvent put up a modal dialog°dONLNdŒ+<7fl(SZVbox. If you have a modal status window frontmost when your pIdle procedure is called, °dONLNd$+fl7˛(S˝you’re°dONLNd+7<C{(_Z
  6122. in no danger.
  6123. °dONLNd9[<jM*'&Macintosh Printing Manager error -8132
  6124. °dONLNd`j<vû* Date Written:  1/1/90°dONLNdvv<Ç´* Last reviewed:  6/14/93 ¡X¡
  6125. *8PR 515 - Printing Manager Q&As(÷ˇ1) of 14(ÏZM.PR.PrtMgr.Q&Asˇ°¿Ù%%DSIDICT:_cv
  6126. currentdict /bu known {bu}if
  6127. userdict /_cv known not{userdict /_cv 30 dict put}if
  6128. _cv begin
  6129. /bdf{bind def}bind def
  6130. currentscreen/cs exch def/ca exch def/cf exch def
  6131. /setcmykcolor where{/setcmykcolor get /cvcmyk exch def}{/cvcmyk{1 sub 4 1 roll 3{3 index add neg dup 0 lt{pop 0}if 3 1 roll}repeat setrgbcolor pop}bdf }ifelse
  6132. /ss{//cf //ca //cs setscreen}bdf
  6133. /stg{ss setgray}bdf
  6134. /strgb{ss setrgbcolor}bdf
  6135. /stcmyk{ss cvcmyk}bdf
  6136. /min1{dup 0 eq{pop 1}if}bdf
  6137. end
  6138. currentdict /bn known {bn}if
  6139. †øÜ◊#ˇ ˇˇˇˇ#◊ 
  6140. IR,Times
  6141. .+6-Macintosh Technical Notes /4/˘
  6142. °dONLNd)*/What is Macintosh Printing Manager error -8132?°dONLNd0)5** ___°dONLNd4AM+*9Error -8132 is generated when the selected printer times °dONLNdmA+M⁄(iI#out. AppleTalk printers monitor the°dONLNdëMY#(u67time between data packets that are sent to them. These °dONLNd»M#Y⁄(uA"devices will wait a maximum of two°dONLNdÎYei(Å6minutes without °dONLNd˚Yie⁄)QLdata until generating a time-out error. Applications such as database report°dONLNdHeqÁ(ç6)generators sometimes require longer than °dONLNdqeÁq⁄)œ/two minutes to sort or format their data. These°dONLNd°q}l(ô6applications may °dONLNd≤ql}⁄)THreceive the -8132 error. One workaround for this problem is to spool the°dONLNd˚}âj(•6Jreport to a file that can be printed when sorting/formatting is completed.°dONLNdFï°í*PAnother possible solution is to change the amount of time the LaserWriter waits °dONLNdñïí°⁄(Ω∞for data until it°dONLNd®°≠(…61times out. Keep in mind that the time-out in the °dONLNdŸ°≠⁄)Î+LaserWriter exists for a reason. Say a user°dONLNd≠πØ(’6!starts printing a large document °dONLNd&≠Øπ⁄)ó;and leaves for the day. About halfway through the document,°dONLNdbπ≈K(·6 the user’s °dONLNdmπK≈⁄)3PMacintosh crashes, leaving the printer waiting without data. In two minutes, the°dONLNdæ≈—¿(Ì6WLaserWriter times out, and is once again available for other users on the net. However °dONLNd≈¿—⁄(Ìfiif the°dONLNd—›7(˘6=time-out is disabled by the first user’s job, the printer is °dONLNdY—7›⁄(˘U useless until rebooted. To avoid°dONLNdz›ÈW(6disabling the °dONLNdà›WÈ⁄)?Stime-out, increase the time-out value so that the device times-out if the job takes°dONLNd‹Èıs(6too long to print, °dONLNdÔÈsı⁄)[Dbut does not time-out for normal delays. This is done by sending the°dONLNd4ıÑ(6Nfollowing Postscript to the LaserWriter with a Postscript downloading utility:,
  6143. Courier
  6144.     °dONLNdÉ
  6145. Æ* serverdict begin 0 exitserver°dONLNd¢"Í*
  6146. * statusdict begin 0 0 0 setdefaulttimeouts
  6147. °dONLNdÕ-99*;See the Apple’s LaserWriter Reference for more information.°dONLNd    EQπ*"The only other way to handle this °dONLNd+EπQ⁄)°<problem is to periodically send some data to the printer. Do°dONLNdhQ]^(y6Gthis about once a minute or so to prevent the printer from timing out. °dONLNdØQ^]⁄(y|Use the PostScriptHandle°dONLNd»]i(Ö64PicComment to send this “tickle” data so that it is °dONLNd¸]i⁄)Î.only sent to PostScript printers that have the°dONLNd+iu&(ë67ability to time-out. (Quickdraw printers won’t see the °dONLNdbi&u⁄(ëD#data.) Another reason for using the°dONLNdÜuÅS(ù6?PostScriptHandle PicComment involves the internal buffering of °dONLNd≈uSÅ⁄(ùqthe LaserWriter driver. The°dONLNd·Åçr(©6LaserWriter driver °dONLNdÙÅrç⁄)ZLmaintains a 4K internal buffer for the PostScript that it sends. If you send°dONLNdAçô˜(µ60just a few characters as your tickle data, they °dONLNdqç˜ô⁄)fl0are buffered in the driver, and the device still°dONLNd¢ô•è(¡6times-out. The only way °dONLNd∫ôè•⁄)wFto ensure that your tickle data makes it to the device is to send a 4K°dONLNd    •±(Õ6+block via the PostScriptHandle PicComment. °dONLNd    ,•±⁄)Ë'Needless to say, sending 4K blocks over°dONLNd    T±Ωõ(Ÿ6AppleTalk once a minute is °dONLNd    o±õΩ⁄)ÉDgoing to cause some network traffic, but it’s still another possible°dONLNd    ¥Ω…V(Â6 workaround.
  6148. °dONLNd    ¿·)*'&Macintosh Printing Manager error -8133
  6149. °dONLNd    Á¸z* Date Written:  1/1/90°dONLNd    ˝¸Å* Last reviewed:  8/1/92°dONLNd
  6150.  */What is Macintosh Printing Manager error -8133?°dONLNd
  6151. D ,** ___°dONLNd
  6152. H8D{*KPrinting Manager error -8133 occurs when the PostScript interpreter of the °dONLNd
  6153. ì8{D⁄(`ôLaserWriter (or any°dONLNd
  6154. ßDPe(l6Iother PostScript printer) generates a PostScript error. A description of °dONLNd
  6155. DeP⁄(lÉthe PostScript command°dONLNd P\‚(x6*that caused the error is displayed in the °dONLNd 1P‚\⁄) .status window. This error often occurs when an°dONLNd `\h%(Ñ6:application sends PostScript directly to the printer, and °dONLNd ö\%h⁄(ÑC%that PostScript contains an error. To°dONLNd ¿ht(ê65debug this problem, look at the PostScript generated °dONLNd ıht÷)˙$by the driver. Hold down the Command°dONLNd h÷t⁄)ƒ-°dONLNd tÄg(ú6F key right after °dONLNd ,tgÄ⁄)ONclicking okay in the Print dialog. A file named PostScript0 will be created in ¡4¡˘
  6156. (÷62) of 14(÷mPR 515 - Printing Manager Q&As+5M.PR.PrtMgr.Q&AsˇD◊#ˇ ˇˇˇˇ#◊ 
  6157. IR,Times
  6158. .+Z-Developer Support Center(-€September 1993 /X/
  6159. °dONLNd<)s(EZ the current °dONLNd s)˛)7Rdirectory. With the 7.x LaserWriter drivers, just select the PostScript File radio°dONLNd_)<5µ(QZbutton in the Print dialog.
  6160. °dONLNd{M<\â*'2Identifying Macintosh’s currently selected printer
  6161. °dONLNdÆ\<hû* Date Written:  1/1/90°dONLNdƒh<t•* Last reviewed:  8/1/92°dONLNd€Ä<åÊ*WHow can I find out which printer the user has selected with the Macintosh Chooser? How °dONLNd2ÄÊå˛(®can I°dONLNd8å<ò(¥Z,change it without going through the Chooser?°dONLNdeò<§N* ___°dONLNdi∞<º*.The type of the currently selected printer is °dONLNdó∞º˛)‘/stored in the System file in 'STR ' resource ID°dONLNd«º<»å(‰Z-8192. This will °dONLNdÿºå»˛)PKbe the name of the driver selected, such as LaserWriter or ImageWriter. The°dONLNd$»<‘g(Zname of °dONLNd,»g‘˛)+Uthe actual printer selected will be in the driver file (same name as the printer type°dONLNdÇ‘<‡ı(¸Z]chosen) in 'PAPA' resource ID -8192. Look at this resource with ResEdit to see what is in it.°dONLNd‡Ï<¯ø*You can change the 'STR ' °dONLNd˙Ïø¯˛)É?and 'PAPA' resources, but it may not work now or in the future.°dONLNd:¯< ( Z$DTS does not recommend changing the °dONLNd^¯ Â)œ)system file or circumventing the Chooser!°dONLNdá¯Â˛)⁄ The°dONLNdå<%(,Z1Chooser is a very complicated piece of software, °dONLNdΩ%˛)È*and it has many dependencies. Implementing°dONLNdË<N(8Zthe °dONLNdÏN˛)Uchooser within your application would make your application dependent on a particular°dONLNdB<(c(DZversion °dONLNdJc(˛)'Pof the system software. Like the Chooser, your application would then have to be°dONLNdõ(<4(PZ+revised each time a new system is released.
  6162. °dONLNd«L<[«*'9How to save Macintosh Page Setup and Print dialog options
  6163. °dONLNd[<gû* Date Written:  5/3/89°dONLNdg<s´* Last reviewed:  6/14/93°dONLNd/<ãô*HHow do I save options set in the Macintosh Page Setup and Print dialogs?°dONLNdxã<óN* ___°dONLNd|£<Ø≈*The only supported method °dONLNdñ£≈Ø˛)â?to save the dialog options is to save the Print Record that was°dONLNd÷Ø<ªß(◊ZLpassed to the PrStlDialog/PrJobDialog calls. This print record contains the °dONLNd"Øßª˛(◊≈options chosen in°dONLNd4ª<«g(„Z=the Page Setup and Print dialogs. Although these options are °dONLNdqªg«˛(„Ösaved in the print record, they°dONLNdë«<”•(ÔZKcannot be used as defaults for the Print dialog. For example, say the user °dONLNd‹«•”˛(Ô√chooses landscape°dONLNdÓ”<fl>(˚Z7printing in the Page Setup dialog, and sets the number °dONLNd%”>fl˛(˚\*of copies to 5 in the Print dialog. If the°dONLNdPfl<Î∞(Zprint record is passed to °dONLNdjfl∞β)tEPrStlDialog, the dialog shows that landscape printing was selected in°dONLNd∞Î<˜ˆ(Z[the print record. However, if that print record is passed to PrJobDialog, number of copies °dONLNd Έ˜˛(is°dONLNd˜<õ(ZDshown as 1, because options in the PrJobDialog are considered to be °dONLNdR˜õ˛(π“job dependent,” as°dONLNdf<‚(+Z opposed to “document dependent.”°dONLNdá<'ê*The best method °dONLNdóê'˛)TJfor saving the print record is to save it as a resource in your document’s°dONLNd‚'<3}(OZGresource fork. Since the print record is already pointed to by a valid °dONLNd    )'}3˛(Oõhandle, creating a resource°dONLNd    E3<?‰([Z%is easy. Here are the required steps:°dONLNd    kK<W**1. Save the refNum returned by CurResFile;°dONLNd    ñW<cÙ* [2. Make sure the resource fork of the document file is opened using OpenResFile (IM I:115).°dONLNd    Úc<o¯* ^3. Now that you have a place to put the resource, you must get the resource manager to create °dONLNd
  6164. Pc¯o˛(ãit°dONLNd
  6165. So<{‹(óZ#for you. First, pick a type and ID °dONLNd
  6166. vo‹{˛)†9for your resource. You can use the Unique ID function (IM°dONLNd
  6167. ∞{<áD(£Z6I:121) to generate the ID. Next, call the AddResource °dONLNd
  6168. Ê{Dá˛(£b$procedure (IM I:124). This procedure°dONLNd á<ì§(ØZtakes four parameters: ¡X¡
  6169. *'PR 515 - Printing Manager Q&As(÷ˇ3) of 14(ÏZM.PR.PrtMgr.Q&AsˇZ◊#ˇ ˇˇˇˇ#◊ 
  6170. IR,Times
  6171. .+6-Macintosh Technical Notes /4/˘,
  6172. Courier
  6173.     °dONLNd)4Ω*#! Parameter  Type     What to Pass°dONLNd"3>ü*
  6174.  --------------------------°dONLNd>=Hl*
  6175. D theData    Handle   The handle to the currently valid print record.°dONLNdÉGRv*
  6176. F theType    ResType  The four character resource type you have chosen.°dONLNd Q\X*
  6177. @ theID      INTEGER  The ID returned from the UniqueID function.°dONLNd [fN*
  6178. > name       Str255   The name for this resource or '' if none.
  6179. °dONLNdJq}Δ*P4. Call WriteResource (IM I:125), and UpdateResFile (IM I:125) to make sure the °dONLNdöqΔ}⁄(ô‰new°dONLNdû}â∞(•6"resource gets saved into the file.°dONLNd¡âï * 95. Reset the currently selected file back to whatever it °dONLNd˙â ï⁄(±>#was before you began the save using°dONLNdï°à(Ω6UseResFile (IM I:117).°dONLNd5≠π)*9The important things to keep in mind when doing this are:°dONLNdo≈—8*:1. Make your resource type something different than those °dONLNd©≈8—⁄(ÌVused by the Print Manager. This°dONLNd…—›ö(˘6prevents the Print Manager °dONLNd‰—ö›⁄)Ç?from getting confused and grabbing the wrong resource. Types to°dONLNd$›È(6)avoid include 'PREC', 'PDEF', and 'POST'.°dONLNdNÈıs* 2. Don’t make any °dONLNd`Èsı⁄)[Jassumptions about the size of the print record. If you really need to know°dONLNd´ıU(6the size, use °dONLNdπıU⁄)=SGetHandleSize.so that if the record gets bigger in the future, your code will still°dONLNd
  6180. 
  6181. 5()6work.°dONLNd
  6182. ±* S3. Be sure to pass the record that you get from your document to PrValidate before °dONLNdf
  6183. ±⁄(5œ    using it.°dONLNdp%˘(A61This ensures that the record gets updated if any °dONLNd°˘%⁄)·-changes have been made to record structure or°dONLNdœ%1ƒ(M6$contents since the record was saved.
  6184. °dONLNdÙIX5*')MacApp and SetRsl print driver resolution
  6185. °dONLNdXdÄ* Date Written:  4/16/92°dONLNd5dpá* Last reviewed:  6/14/93°dONLNdM|àr*We’ve been trying °dONLNd_|rà⁄)ZGto use the standardPrint handler from MacApp 2 to print some views. The°dONLNdßàîì(∞6problem is that we would °dONLNd¿àìî⁄){Dlike the printout to come out at 300 dpi on the LaserWriter, and the°dONLNdî†ô(º6Uprint handler’s device resolution fields (which come from the device driver) tell it °dONLNdZîô†⁄(º∑
  6186. to draw at 72°dONLNdh†¨†(»6Ndpi. How, can I get a PenSize(1,1); MoveTo(100,100); LineTo(300,300); draw at °dONLNd∂††¨⁄(»æ 300 dpi and°dONLNd¬¨∏U(‘6Cmake a nice fine line? Please refer me to the needed documentation.°dONLNd∏ƒ** ___°dONLNd
  6187. –‹í*OThe mechanism by which your application can find out the chosen printer’s real °dONLNdY–í‹⁄(¯∞resolution, and°dONLNdi‹ËJ(6;then draw with it, is documented “Meet PrGeneral, the Trap °dONLNd§‹JË⁄(hThat Makes the Most of the°dONLNdøËÙv(6Printing Manager,” °dONLNd“ËvÙΩ)^in issue #3 of °dONLNd·ËΩÙ‚)Gdevelop°dONLNdËË‚Ù⁄)%2 magazine (July 1990). You can find it, along with°dONLNdÙ±(6Rits accompanying code and application, on the Developer CD, E.T.O., and AppleLink.°dONLNdn 0*The °dONLNdr 0⁄)FDTS Sample Code SC.009.FracApp300 on the Developer CD shows how to use°dONLNdπ$(@60PrGeneral in an application built with MacApp 2.
  6188. °dONLNdÍ?N»**@Printing patterns at higher resolutions with GetRslData & SetRsl
  6189. °dONLNd    +NZÄ* Date Written:  11/7/90°dONLNd    BZfá* Last reviewed:  6/14/93°dONLNd    Zr~Q*EIs there a way that I can make my Macintosh fill patterns print at a °dONLNd    ürQ~⁄(öohigher resolution (more than°dONLNd    º~ä
  6190. (¶6672 dpi), but have my patterns still print as patterns?°dONLNd    Ûäñ** ___ ¡4¡˘
  6191. *$4) of 14(÷mPR 515 - Printing Manager Q&As+5M.PR.PrtMgr.Q&Asˇz◊#ˇ ˇˇˇˇ#◊ 
  6192. IR,Times
  6193. .+Z-Developer Support Center(-€September 1993 /X/
  6194. °dONLNd)<5h(QZ=To make your patterns print at the printer’s resolution, you °dONLNd=)h5˛(QÜneed to use Printing Manager°dONLNdZ5<A≈(]ZPrGeneral’s GetRslData and °dONLNdu5≈A˛)â@SetRsl opcodes to get and set the resolution, and you must scale°dONLNd∂A<MË(iZ%the pattern to match. Let me explain.°dONLNd‹Y<eÕ*UIf we do not scale our patterns up to the printer’s resolution before print time, we °dONLNd1YÕe˛(ÅΠ   would get°dONLNd;e<q(çZ*“big chunky” patterns because the printer °dONLNdeeq˛)À2driver would need to scale the patterns on the fly°dONLNdòq<}(ôZ*from 72 dpi to its resolution. Therefore, °dONLNd¬q}˛)«2we use the “cookie cutter” approach to “place” the°dONLNdı}<â§(•Zpattern into the object °dONLNd
  6195. }§â˛)hMthat is being filled. The size of the cookie cutter (that is, the destination°dONLNd[â<ï∂(±ZPRect) depends on the “scaleFactor”. For example, a scaleFactor of 2 will have a °dONLNd´â∂ï˛(±‘destination rect°dONLNdºï<°+(ΩZ2of 16 x 16. We will then CopyBits the pattern one °dONLNdÓï+°˛)Ô.square at a time into the object that is being°dONLNd°<≠X(…Zfilled.°dONLNd%π<≈^*XRefs:°dONLNd,≈<—ç* Inside Macintosh°dONLNd<≈ç—
  6196. )Q Volume V, pages 410-416°dONLNdU—<›ó(˘Z“Meet PrGeneral,” °dONLNdg—ó›¿)[develop,°dONLNdo—¿›Ú))
  6197.  July 1990
  6198. °dONLNdzı<È( Z@Call Printing Mgr’s bottleneck to send StdText to printer driver
  6199. °dONLNdª<§* Date Written:  11/7/90°dONLNd“<´* Last reviewed:  6/14/93°dONLNdÍ(<4j*We need °dONLNdÚ(j4˛).Nto use the Macintosh toolbox call StdText instead of DrawChar, DrawString, and°dONLNdA4<@Ô(\ZWDrawText to accomplish horizontal scaling and fractional point sizes, but StdText does °dONLNdò4Ô@˛(\
  6200. not°dONLNdú@<LJ(hZ6work on the LaserWriter IISC. Is there any workaround?°dONLNd”L<XN* ___°dONLNd◊d<p¿*The problem is that you are °dONLNdÛd¿p˛)ÑCcalling the low-level bottleneck directly, and the Printing Manager°dONLNd7p<| (òZ0has replaced the bottleneck completely with its °dONLNdgp |˛)‰+own. So when you are actually printing, the°dONLNdì|<àv(§Z
  6201. print driver °dONLNd†|và˛):Pwill not see your call to StdText. The work-around for this is to call the Print°dONLNdÒà<îfl(∞ZXManager’s bottleneck itself when you are printing. You can do this in the following way:,
  6202. Courier
  6203.     °dONLNdJ†<´æ*/* typedef the function */°dONLNde™<µÜ*
  6204. Btypedef pascal void (*StdTextProcPtr)( short, Ptr, Point, Point );°dONLNd®æ<…*,void tstDrawStuff( pInfo, thePort, pageNum )°dONLNd’»<”}*
  6205.  
  6206. TPrint pInfo;°dONLNd„“<›å*
  6207. GrafPtr thePort;°dONLNdÙ‹<ÁØ*
  6208. unsigned short pageNum;°dONLNd Ê<ÒA*
  6209. {°dONLNd<˚Y*
  6210. 9   StdTextProcPtr Proc;     /* declare a variable here */°dONLNdH<√*/* do your clipping etc. */°dONLNdd<#‹* /* TEST -- no good w/o PriMon */°dONLNdÖ"<-π*
  6211. /* do your moveto etc. */°dONLNdü6<A*(/* Is there a replacement bottleneck ?*/°dONLNd»@<K»*
  6212. if ( thePort->grafProcs )  {°dONLNdÂJ<U¬*
  6213. N    Proc = (StdTextProcPtr)thePort->grafProcs->textProc; /* yes, so grab it */°dONLNd4T<_m*
  6214. =    (*Proc)( strlen("HELLO") , (Ptr) "HELLO", numer, denom );°dONLNdr^<iA*
  6215. }°dONLNdth<sÊ*
  6216. "/* else just call standard text */°dONLNdór<}A*
  6217. } ¡X¡
  6218. *=PR 515 - Printing Manager Q&As(÷ˇ5) of 14(ÏZM.PR.PrtMgr.Q&Asˇå◊#ˇ ˇˇˇˇ#◊ 
  6219. IR,Times
  6220. .+6-Macintosh Technical Notes /4/˘
  6221. °dONLNd)ô*This technique will work °dONLNdô)⁄)Å>in both background and foreground printing. I have tested this°dONLNdX)5≥(Q6Vsolution on the Personal LaserWriter SC and the LaserWriter IINTX, and it prints fine.
  6222. °dONLNdØM\Ω*'<Modifying PDEFs to have printer driver jump into dialog code
  6223. °dONLNdÏ\hÄ* Date Written:  11/9/90°dONLNdhtá* Last reviewed:  6/14/93°dONLNdÄå£*Could you please point me °dONLNd5Ä£å⁄)ã<to the correct section in “Learning to Drive” (or send me an°dONLNdråò((¥66example) that we would need to modify the appropriate °dONLNd®å(ò⁄(¥F"PDEF resource in order to have the°dONLNdÀò§¨(¿6driver jump to our dialog code?°dONLNdΧ∞** ___°dONLNdÔº»í*KPages 15-18 discuss the contents of the various PDEFs. You will need patch °dONLNd:ºí»⁄(‰∞the appropriate°dONLNdJ»‘ä(6OPDEF to get your required functionality. You should also realize that patching °dONLNdô»ä‘⁄(®PDEFs is not an°dONLNd©‘‡≈(¸6&easy task, nor will it always survive °dONLNdœ‘≈‡⁄)≠7“new” Macintosh LaserWriter driver releases. I want you°dONLNd‡ÏP(6?to know that before you go too far down the PDEF patching road.°dONLNdG¯Ü*IBy the way, we do know of a couple of developers that have patched PDEFs °dONLNdê¯Ü⁄( §successfully. The°dONLNd¢K(,6@following paragraphs are a “high-level” look at patching a PDEF:°dONLNd„()*To °dONLNdÊ)(⁄)Xpatch a PDEF, you must write an installer application that lets users choose the printer°dONLNd?(4k(P6driver they want °dONLNdP(k4⁄)SHto modify via Standard File. You can cause Standard File to display only°dONLNdô4@m(\6printer drivers by °dONLNd¨4m@⁄)UMtelling it to display only files of type “PRER”. Once the user has selected a°dONLNd˙@Lü(h6Qdriver you need to scan the driver for the PDEF 0 and 1 resources. When you find °dONLNdK@üL⁄(hΩ one of these°dONLNdXLXú(t6you read it in and modify it.°dONLNdvdp1*9However, I'll give you a quick overview of what you need °dONLNdØd1p⁄(åO!to do. PDEF 0 & 1 both start with°dONLNd—p|v(ò6jump tables (a table °dONLNdÊpv|⁄)^Hof JMP instructions followed by the PC relative address to jump to). The°dONLNd/|àÛ(§6+JMP to PrClosePage always begins at offset °dONLNdZ|Ûà⁄)€/12. So what your installer needs to do after it°dONLNdäàî–(∞6cloads the resource is grab the eighth word in the resource. That is the offset to the actual start °dONLNdÌà–î⁄(∞Óof°dONLNdî†N(º6Athe PrClosePage code. Then you have to resize the handle so that °dONLNd1îN†⁄(ºlit is big enough to hold your°dONLNdO†¨ (»6.patch and then BlockMove {IM II-44} your code °dONLNd}† ¨⁄)Û)into the end of the handle. The following°dONLNdߨ∏Ç(‘6illustration might help:,
  6224. Courier
  6225.     °dONLNd¿ƒœä*J         JMP $0486              << Note: some PDEF's have multiple JMPs at°dONLNd ŒŸ{*
  6226. G* - - - - - - - - - - - - - *            the beginning of the code. The°dONLNdSÿ„è*
  6227. K*                           *            original offset to PrClosePage was°dONLNdü‚Ì*
  6228. /* >> Original PDEF code  << *            $0386.°dONLNdœÏ˜©*
  6229. *                           *°dONLNd̈è*
  6230. K$0386 --> PrClosePage           << Note: most PDEF's have multiple printing°dONLNd    9 +*
  6231. 7*                           *            calls defined.°dONLNd    q
  6232. ©*
  6233. *                           *°dONLNd    è©*
  6234. * - - - - - - - - - - - - - *°dONLNd    ≠)©*
  6235. $0486 --> {{{  Your Code  }}}°dONLNd    À(3Ö*
  6236. I*                           *   << You resize the resource handle to this°dONLNd
  6237. 2=Ö*
  6238. I*                           *            and blockmove your code in here.°dONLNd
  6239. _<G©*
  6240. *                           *°dONLNd
  6241. }FQ©*
  6242. * - - - - - - - - - - - - - *°dONLNd
  6243. õP[Ö*
  6244. I         JMP $0386              << At this point we jump into the printer°dONLNd
  6245. ÂZeô*
  6246. M                                      driver's original code for PrClosePage.
  6247. °dONLNd 3p|U*?Note: The previous illustration is not to scale nor completely °dONLNd rpU|⁄(òsaccurate in regards to the°dONLNd ç|à¿(§6Yaddresses used. Please consult “Learning To drive” for the correct offsets for each PDEF. ¡4¡˘
  6248. *26) of 14(÷mPR 515 - Printing Manager Q&As+5M.PR.PrtMgr.Q&Asˇ.◊#ˇ ˇˇˇˇ#◊ 
  6249. IR,Times
  6250. .+Z-Developer Support Center(-€September 1993 /X/
  6251. °dONLNd<)À(EZRThen replace the original offset to PrClosePage with the offset to your new code. °dONLNdRÀ)˛(EÈRemember°dONLNd[)<52(QZ8that this is PC relative so you would calculate it like °dONLNdì)25˛)ˆ)this: If the original PrClosePage JMP was°dONLNdΩ5<Aä(]ZDJMP 10(SP) and the size of the original PDEF was 50 bytes, then you °dONLNd5äA˛(]®need to replace the JMP°dONLNdA<M(iZ+10(SP) with JMP 50-16(SP). In other words, °dONLNdDAM˛)‹,you need to JMP to what was formerly the end°dONLNdqM<Y(uZ)of the PDEF resource but what is now the °dONLNdöMY˛)“/beginning of your code (subtract 16 because the°dONLNd Y<eÕ(ÅZWoffset table is 16 bytes long. Refer to “Learning to Drive” for more details). Then on °dONLNd!YÕe˛(ÅÎ
  6252. the end of°dONLNd,e<qz(çZ your code, °dONLNd7ezq˛)>Eadd a JMP ((SizeOfJumpTable + originalOffset) – (sizeofOriginalPDEF +°dONLNd}q<}§(ôZISizeOfYourCode))(SP). Your code will end with a JMP to a negative offset °dONLNdΔq§}˛(ô¬off the PC back to°dONLNdŸ}<â√(•Zthe original PrCloseRoutine.°dONLNdˆï<°ƒ*If you are willing to support °dONLNd˛)àAonly system software later than version 3.3 (basically that means°dONLNdV°<≠.(…Z0that you won’t be supporting Macintosh 512K and °dONLNdܰ.≠˛)Ú(512KE computers), you don’t have to deal°dONLNdØ≠<πñ(’ZCwith all the PDEF changing, and you can simply patch out the $A8FD °dONLNdÚ≠ñπ˛(’¥trap and look for the°dONLNdπ<≈Ö(·Zproper selector °dONLNdπÖ≈˛)IMon the stack. (Use SysEnvirons to be sure that you are on a system later than°dONLNdf≈<—Í(ÌZ$version 3.3) This will work because °dONLNdä≈Í—˛)Æ<the newer libraries (that is, any library that shipped since°dONLNd«—<›Ò(˘Z'the Macintosh II shipped) first checks °dONLNdÓ—Ò›˛)µ:for the trap and jumps there if the trap exists so even if°dONLNd)›<ÈR(Z>the application has linked in the printing library they still °dONLNdg›RÈ˛(p"end up calling the trap on systems°dONLNdäÈ<ıh(Z
  6253. after 3.3.
  6254. °dONLNdï
  6255. <Ê*'?Determining if printer supports color and/or grayscale printing
  6256. °dONLNd’<(§* Date Written:  3/14/91°dONLNdÏ(<4•* Last reviewed:  8/1/92°dONLNd@<L|*
  6257. Is there any °dONLNd@|L˛)@Lway to determine whether I’m printing to either a color printer or a printer°dONLNd]L<Xt(tZBsimulating color, such as the LaserWriter set for Color/Grayscale?°dONLNd†X<dN* ___°dONLNd§p<|c*>Check the grafPort returned by your call to PrOpenDoc. If the °dONLNd‚pc|˛(òÅ rowBytes of the grafPort is less°dONLNd|<àÎ(§Z!than 0, the Printing Manager has °dONLNd$|Îà˛)Ø2returned a color grafPort. You can then make Color°dONLNdWà<îè(∞ZQuickDraw calls °dONLNdgàèî˛)SLinto this grafPort. LaserWriter driver version 6.0 and later returns a color°dONLNd¥î<†´(ºZMgrafPort from the PrOpenDoc call, if the Color/Grayscale button has been set.°dONLNd¨<∏*.The following code fragment demonstrates this:,
  6258. Courier
  6259.     °dONLNd1ƒ<œÅ*A(* This function determines whether the port passed to it is a *)°dONLNdsŒ<ŸÅ*
  6260. A(* color port. If so, it returns TRUE.                         *)°dONLNdµÿ<„O*
  6261. 7FUNCTION IsColorPort(portInQuestion: GrafPtr): BOOLEAN;°dONLNdÌ‚<ÌU*
  6262. BEGIN°dONLNdÛÏ<˜'*
  6263. /  IF portInQuestion^.portBits.rowBytes < 0 THEN°dONLNd    #ˆ<Ø*
  6264.     IsColorPort := TRUE°dONLNd    ;< Z*
  6265.   ELSE°dONLNd    B
  6266. <π*
  6267.     IsColorPort := FALSE;°dONLNd    \<P*
  6268. END;
  6269. °dONLNd    a*<6ˇ*+A third-party printer driver should return °dONLNd    å*ˇ6˛)√9the type of grafPort that represents the abilities of its°dONLNd    Δ6<BD(^Z9printer. Therefore, if the printer supports color and/or °dONLNd    ˇ6DB˛(^b$grayscale, and if Color QuickDraw is°dONLNd
  6270. $B<N2(jZ7present, the application will receive a color grafPort °dONLNd
  6271. [B2N˛)ˆ*after calling PrOpenDoc. Otherwise, if the°dONLNd
  6272. ÜN<Zp(vZ
  6273. Macintosh °dONLNd
  6274. êNpZ˙)4Myou’re running on does not support Color QuickDraw, you should return a black°dONLNd
  6275. ›N˙Z˛(v-°dONLNd
  6276. fiZ<fô(ÇZand-white grafPort. ¡X¡
  6277. *TPR 515 - Printing Manager Q&As(÷ˇ7) of 14(ÏZM.PR.PrtMgr.Q&Asˇò◊#ˇ ˇˇˇˇ#◊ 
  6278. IR,Times
  6279. .+6-Macintosh Technical Notes /4/˘
  6280. °dONLNd,0*(Using LaserWriter fonts with StyleWriter
  6281. °dONLNd),8Ä* Date Written:  3/22/91°dONLNd@8Dá* Last reviewed:  6/14/93°dONLNdXP\*/Can StyleWriter use all the Adobe fonts for my °dONLNdáP\⁄)¸&LaserWriter? Can StyleWriter print the°dONLNdÆ\h/(Ñ66encapsulated PostScript drawings I’ve developed? Does °dONLNd‰\/h⁄(ÑMTrueType software come with the°dONLNdhtS(ê6 StyleWriter?°dONLNdtÄ** ___°dONLNdåò”*'The difference between the StyleWriter °dONLNd<å”ò⁄)ª7and a regular LaserWriter (other than one’s got a laser°dONLNdtò§°(¿6and the other doesn’t) is that °dONLNdìò°§⁄)âBthe LaserWriter has PostScript built-in; the StyleWriter does not.°dONLNd÷§∞¶(Ã6The StyleWriter, in fact, has °dONLNdÙ§¶∞⁄)é?nothing built-in, and only recognizes basic “put this dot here”°dONLNd4∞ºk(ÿ6Ctypes of commands. Even sending it pure ASCII accomplishes nothing.°dONLNdx»‘´*UTrueType software is shipped with the StyleWriter, because it can image fonts at any °dONLNdÕ»´‘⁄(…
  6282. resolution°dONLNdÿ‘‡ü(¸6Pwith excellent quality, much like PostScript. The TrueType software is intended °dONLNd(‘ü‡⁄(¸Ω for users of°dONLNd5‡Ï<(68system versions 6.0.7 and later, but prior to System 7. °dONLNdm‡<Ïs(Z    System 7 °dONLNdv‡sÏö)7includes°dONLNd~‡öÏ⁄)'  support for°dONLNdãϯJ(6    TrueType.°dONLNdï¯*(You can use PostScript images and fonts °dONLNdΩ¯⁄)‡*with the StyleWriter, but just as with the°dONLNdËÎ(86+ImageWriter, you’ll have to have something °dONLNdÎ⁄)”.that images them in memory before sending them°dONLNdB(x(D6Mto the printer (in other words, a Macintosh-resident PostScript interpreter).
  6283. °dONLNdê@OC*',Personal LaserWriter LS 1.1 driver is faster
  6284. °dONLNdΩO[z* Date Written:  8/9/91°dONLNd”[gá* Last reviewed:  6/14/93°dONLNdÎs¬*SMy LaserWriter LS is very slow when printing from my Macintosh SE. Any suggestions?°dONLNd?ã** ___°dONLNdCó£Á**Use the new LaserWriter LS driver version °dONLNdmóÁ£⁄)œ31.1 or later. It was released after System 7.0, and°dONLNd°£ØÛ(À6.is available on AppleLink or from your dealer.°dONLNd–ª«D*9If you’re printing Word files, Microsoft’s TrueType INIT °dONLNd    ªD«⁄(„bwill help. It’s available from°dONLNd(«”r(Ô6GMicroSoft Technical Support or from commercial bulletin board services.
  6285. °dONLNdpÎ˙´*'9ImageWriter II 6.1 & 7.0 driver PrGeneral/PrStlDialog bug
  6286. °dONLNd™˙Ä* Date Written:  9/11/91°dONLNd¡á* Last reviewed:  6/14/93°dONLNdŸ*1*If an °dONLNdfl1*⁄)Wapplication uses PrGeneral to set draftBits mode on an ImageWriter II (using the 6.1 or°dONLNd7*6U(R6
  6287. 7.0 drivers) °dONLNdD*U6⁄)=Mand then does a PrStlDialog, a fatal crash occurs. This happens with both the°dONLNdí6B3(^67AppleTalk and non-AppleTalk drivers. This only happens °dONLNd…63B⁄(^Qon Macintosh systems with Color°dONLNdÈBNR(j6
  6288. QuickDraw.°dONLNdÙZfY* The problem °dONLNdZYf⁄)ALis connected to the two 'dctb' resources which were added in the 6.1 driver.°dONLNdMfr(é63When the landscape icon is being grayed out (since °dONLNdÄfr⁄)˝(it’s unsupported in draftBits mode), the°dONLNd©r~j(ö6Idriver is jamming the gray pen pattern directly into the GrafPort. While °dONLNdÚrj~⁄(öàthis brute-force method°dONLNd    
  6289. ~ä†(¶6works fine with GrafPorts, °dONLNd    %~†ä⁄)à<the 'dctb' resources make the Dialog Manager use a CGrafPort ¡4¡˘
  6290. (÷68) of 14(÷mPR 515 - Printing Manager Q&As+5M.PR.PrtMgr.Q&AsˇZ◊#ˇ ˇˇˇˇ#◊ 
  6291. IR,Times
  6292. .+Z-Developer Support Center(-€September 1993 /X/
  6293. °dONLNd<)fl(EZWnow. Jamming the pattern into this CGrafPort as if it were a GrafPort makes a mess and °dONLNdWfl)˛(E˝causes°dONLNd^)<5ó(QZMa fatal crash, manifesting itself as a “division by zero” error, for example.°dONLNd¨A<M–*To work around the problem, °dONLNd»A–M˛)î<check to see if you are printing to a 6.1 or 7.0 ImageWriter°dONLNdM<Y‡(uZZdriver, and if so, do the style dialog before setting draftBits. The disadvantage of this °dONLNd_M‡Y˛(u˛is that°dONLNdgY<e:(ÅZ8setting draftBits before calling PrStlDialog causes the °dONLNdüY:e˛)˛'50% reduction and landscape controls to°dONLNd«e<q√(çZTbe disabled, and this method doesn’t. Therefore, after the style dialog, you should °dONLNde√q˛(ç· check to see°dONLNd(q<}Ô(ôZ(if the user selected landscape printing °dONLNdPqÔ}˛)≥5or 50% reduction by calling PrGeneral (getRotnOp) and°dONLNdÜ}<âˆ(•Z&checking bit 3 of the wDev field (See °dONLNd¨}ˆâ˛)∫1“Learning To Drive” on the Developer CDs for more°dONLNdfiâ<ïÌ(±Z]about the wDev.) If the user selected either of those options, display a dialog warning them °dONLNd;âÌï˛(± that°dONLNd@ï<°ß(ΩZthose features will be °dONLNdWïß°˛)kEignored. Then, call PrGeneral to set draftBits and continue normally.°dONLNdù°<≠Ö(…ZEPrGeneral will adjust the print record so that options not supported °dONLNd‚°Ö≠˛(…£with draftBits are turned°dONLNd¸≠<π5(’Z6off. If a non 6.1/7.0 ImageWriter driver is used, the °dONLNd2≠5π˛)˘*code should set draftBits as usual, before°dONLNd]π<≈õ(·Zthe PrStlDialog call.°dONLNds—<›p*AThis workaround is the better alternative to hacking the 'dctb's °dONLNd¥—p›˛(˘éout of the driver or patching°dONLNd“›<ÈÀ(Zaround the problem, although °dONLNdÔ›ÀÈ˛)è@it doesn’t help 7.0 users running applications that already make°dONLNd0È<ıÂ(Z!use of the draftBits option. The °dONLNdQÈÂı˛)©4following Pascal snippet demonstrates how to use the°dONLNdÜı<y(Z workaround:,
  6294. Courier
  6295.     °dONLNdí
  6296. <^*:(* Sample snippet that demonstrates how to work-around the°dONLNdÕ<"T*
  6297. 8   'dctb' bug in the ImageWriter II 6.1 and 7.0 drivers.°dONLNd!<,'*
  6298. /   Bug causes a crash when doing a style dialog°dONLNd6+<6*
  6299. *   after setting draftbits with PrGeneral.°dONLNda5<@K*
  6300.  *)°dONLNdeI<TA*{°dONLNdgS<^'*
  6301. /  What's what in the code snippet that follows.°dONLNdög<r◊*  thePrRecHdl        : THPrint;°dONLNd∫q<|Ê*
  6302. "  rslData            : TSetRslBlk;°dONLNd›{<ÜÎ*
  6303. #  draftData          : TDftBitsBlk;°dONLNdÖ<êÎ*
  6304. #  rotnData           : TGetRotnBlk;°dONLNd%è<ö◊*
  6305.   isBadImageWriter   : Boolean;°dONLNdEô<§◊*
  6306.   isLandscape        : Boolean;°dONLNde£<Æ◊*
  6307.   isReduced          : Boolean;°dONLNdÖ≠<∏A*
  6308. }°dONLNdá¡<Ã}*
  6309.       PrOpen;°dONLNdï’<‡Õ*    IF (PrError = noErr) THEN°dONLNd≥fl<Íi*
  6310.         BEGIN°dONLNdΩÛ<˛‹*       PrintDefault(thePrRecHdl);°dONLNdfi<◊*      IF (PrError = noErr) THEN°dONLNd˛<s*
  6311.       BEGIN°dONLNd
  6312. %<0m*={See if we're using a version 6.1 or 7.0 ImageWriter driver.}°dONLNdH9<DJ*6        IF (thePrRecHdl^^.prStl.wDev DIV 256) = 1 THEN°dONLNdC<Nê*
  6313. D          isBadImageWriter := (PrDrvrVers = 61) OR (PrDrvrVers = 70)°dONLNdƒM<Xx*
  6314.         ELSE°dONLNd—W<b*
  6315. $          isBadImageWriter := FALSE;°dONLNd    k<v˙*&        IF NOT (isBadImageWriter) THEN°dONLNd    (u<Ä}*
  6316.  
  6317.         BEGIN°dONLNd    6â<î6*2{Set draftBits mode now, if not our special case.} ¡X¡
  6318. *&PR 515 - Printing Manager Q&As(÷ˇ9) of 14(ÏZM.PR.PrtMgr.Q&Asˇ
  6319. ¶◊#ˇ ˇˇˇˇ#◊ 
  6320. IR,Times
  6321. .+6-Macintosh Technical Notes /4/˘,
  6322. Courier
  6323.     °dONLNd'2Ô*!+          draftData.iOpCode := draftBitsOp;°dONLNd,1<Í*
  6324. *          draftData.hPrint := thePrRecHdl;°dONLNdW;F∏*
  6325.            PrGeneral(@draftData);°dONLNdxOZT*         END;°dONLNdÖcnÜ*{Do the style dialog.}°dONLNdúwÇÍ**        IF (PrStlDialog(thePrRecHdl)) THEN°dONLNd«ÅåÃ*
  6326. $          IF (isBadImageWriter) THEN°dONLNdÏãñc*
  6327.           BEGIN°dONLNd¸ü™0*8{If so, see if they selected rotation or 50% reduction.}°dONLNd@≥æÍ**            rotnData.iOpCode := getRotnOp;°dONLNdkΩ»Ô*
  6328. +            rotnData.hPrint := thePrRecHdl;°dONLNdó«“Ω*
  6329. !            PrGeneral(@rotnData);°dONLNdπ€Ê*/            isLandscape := rotnData.fLandscape;°dONLNdÈÔ˙?*;            isReduced := BTst(thePrRecHdl^^.prStl.wDev, 3);°dONLNd%*4{If so, warn them that those things will be ignored.°dONLNdZ
  6330. !*
  6331. 5 Preferably use something other than DebugStr…      }°dONLNdõ!,*0            IF (isLandscape) OR (isReduced) THEN°dONLNdÃ+6q*
  6332. E              DebugStr('Bad ImageWriter; landscape and/or reduced.');°dONLNd?J*2{Now, set draftBits mode, since we didn't before.}°dONLNdES^˘*-            draftData.iOpCode := draftBitsOp;°dONLNds]hÙ*
  6333. ,            draftData.hPrint := thePrRecHdl;°dONLNd†gr¬*
  6334. "            PrGeneral(@draftData);°dONLNd√{Ü^*          END;°dONLNd“èöÙ*,          IF (PrJobDialog(thePrRecHdl)) THEN°dONLNdô§c*
  6335.           BEGIN°dONLNd≠∏w*            {Print}°dONLNd$¡Ã^*          END;°dONLNd3À÷J*
  6336.  
  6337.       END;°dONLNd>’‡@*
  6338.     END;°dONLNdGÈÙT*     PrClose;
  6339. °dONLNdT k*&2How to abort printing while PrPicFile is executing
  6340. °dONLNdá&Ä* Date Written:  9/27/91°dONLNdû&2á* Last reviewed:  6/14/93°dONLNd∂>Jì*OCan I abort printing from within PrPicFile? My attempts haven’t been succesful.°dONLNdJV** ___°dONLNd
  6341. bnº*"The following Pascal procedure is °dONLNd,bºn·)§roughly°dONLNd3b·nı)% the °dONLNd8bın⁄).same as the default idle procedure—the one the°dONLNdgnzO(ñ6>system supplies for you when you don’t supply one of your own: ¡4¡˘
  6342. *@10)
  6343.  of 14(÷mPR 515 - Printing Manager Q&As+5M.PR.PrtMgr.Q&Asˇ◊#ˇ ˇˇˇˇ#◊ 
  6344. IR,Times
  6345. .+Z-Developer Support Center(-€September 1993 /X/,
  6346. Courier
  6347.     °dONLNd<(√(DZprocedure MyPIdleProcedure;°dONLNd'<2U*
  6348.   var°dONLNd"1<<Ê*
  6349. "    pIdleEventRecord: EventRecord;°dONLNdE;<F_*
  6350.   begin°dONLNdME<PO*
  6351. 7    if GetNextEvent(keyDownMask, pIdleEventRecord) then°dONLNdÖO<Zs*
  6352.       begin°dONLNdëY<dm*
  6353. =        if ((BitAnd(pIdleEventRecord.message, charCodeMask) =°dONLNd–c<n√*
  6354.           longint('.')) and°dONLNdÏm<xr*
  6355. >        (BitAnd(longint(pIdleEventRecord.modifiers), cmdKey) =°dONLNd,w<ÇØ*
  6356.           cmdKey)) then°dONLNdDÅ<å·*
  6357. !            PrSetError(iPrAbort);°dONLNdfã<ñn*
  6358.  
  6359.       end;°dONLNdqï<†Z*
  6360.   end;
  6361. °dONLNdx´<∑Ú*)(This is written in Think Pascal, but it °dONLNd°´Ú∑˛)∂3should work fine under MPW Pascal if you change the°dONLNd’∑<√Ÿ(flZ“BitAnd” functions to “BAND”.)°dONLNdÙœ<€û*CAs you can see, the system aborts when you press Command-period by °dONLNd7œû€˛(˜ºusing PrSetError to°dONLNdK€<Áì(ZFthe constant iPrAbort, which is the same error returned when the user °dONLNdë€ìÁ˛(±clicks “Cancel” in the°dONLNd®Á<Ûi(ZCstyle or job dialogs. If you set the error to iPrAbort, the system °dONLNdÎÁiÛ˛(á will take care of the rest. Your°dONLNd Û<ˇÕ(ZRprint loop will also gracefully cancel, provided you follow the guidelines in the °dONLNd^ÛÕˇ˛(Π   Macintosh°dONLNdhˇ< ('Z,Technical Note “A Printing Loop That Cares.”
  6362. °dONLNdï#<2O*'(Disabling ImageWriter’s initial formfeed
  6363. °dONLNdæ2<>§* Date Written:  1/23/92°dONLNd’><J´* Last reviewed:  6/14/93°dONLNdÌV<bn*    When our °dONLNdˆVnb˛)2Tproduct-to-be prints to the ImageWriter II there is an automatic (and undesirable in°dONLNdKb<n¨(äZour product) sheet feed °dONLNdcb¨n˛)pEbefore actual printing begins. To make matters worse, it always feeds°dONLNd©n<z§(ñZN11", even though our form is a different length. Is there a way to avoid this?°dONLNd¯z<ÜN* ___°dONLNd¸í<û§*HThe ImageWriter ejects a page before printing with the “No Gaps” option °dONLNdDí§û˛(∫¬selected because it°dONLNdXû<™g(ΔZassumes °dONLNd`ûg™˛)+Uthat the page is aligned with a small gap between the perforation and the print head.°dONLNd∂™<∂Î(“Z`So the printer ejects the page and re-aligns the print head at the perforation of the next page.°dONLNd¬<Œ    *)The sample code below illustrates how to °dONLNd@¬    Œ˛)Õ0prevent that nasty form feed from occurring. The°dONLNdqŒ<⁄O(ˆZ8program temporarily disables the “No Gaps” option if it °dONLNd©ŒO⁄˛(ˆm$is selected until after PrOpenDoc is°dONLNdŒ⁄<Ê|(Z>called, preventing a formfeed from occurring. After PrOpenDoc °dONLNd ⁄|Ê˙(öis called, the program re°dONLNd%⁄˙Ê˛)~-°dONLNd&Ê<ÚÕ(Zenables the “No Gaps” option.°dONLNdD˛<
  6364. 4*1Please note that this sample only works with the °dONLNdu˛4
  6365. ˛)¯%ImageWriter II and the ImageWriter LQ°dONLNdõ
  6366. <È(2ZWprinters—probably the only series that supports the “No Gaps” option. The sample shows °dONLNdÚ
  6367. È˛(2how°dONLNdˆ<"ñ(>ZIto check for these types of printers, so you shouldn’t have any problems.
  6368.     °dONLNd@.<9ë*PROGRAM NoGapsWA;°dONLNdRB<MU*{$U-}°dONLNdXL<Wã*
  6369. CUSES PasInOut,Memtypes,QuickDraw,OSIntf,ToolIntf,PackIntf,MacPrint;°dONLNdú`<kU*CONST°dONLNd¢j<uå*
  6370.   bDevLaser = 3;°dONLNd≥t<»*
  6371.   bDevImageWriter     =   1;°dONLNd–~<â»*
  6372.   bDevImageWriterLQ   =   5; ¡X¡
  6373. *1PR 515 - Printing Manager Q&As(÷˙11)
  6374.  of 14(ÏZM.PR.PrtMgr.Q&Asˇ
  6375. Ï◊#ˇ ˇˇˇˇ#◊ 
  6376. IR,Times
  6377. .+6-Macintosh Technical Notes /4/˘,
  6378. Courier
  6379.     °dONLNd(—*%PROCEDURE DrawStuff(theWorld : Rect);°dONLNd&'2î*
  6380. L  { Draw whatever you want here. Make sure it fits in the world rectangle. }°dONLNds1<1*
  6381. BEGIN°dONLNdy;Fw*
  6382.   MoveTo(100, 100);°dONLNdçEPü*
  6383.   DrawString('testing...');°dONLNd´OZ,*
  6384. END;°dONLNd∞cn—*%FUNCTION HiByte(word: INTEGER): Byte;°dONLNd÷mx1*
  6385. BEGIN°dONLNd‹wÇï*
  6386.   HiByte := word DIV 256;°dONLNdˆÅå,*
  6387. END;°dONLNd˚ï†Å*PROCEDURE PrintStuff;°dONLNdü™'*
  6388. VAR°dONLNd©¥Ü*
  6389.   thePrRec:   THPrint;°dONLNd,≥æã*
  6390.   thePrPort:  TPPrPort;°dONLNdDΩ»ê*
  6391.   theStatus:  TPrStatus;°dONLNd]«“Ü*
  6392.   oldPort:    GrafPtr;°dONLNdt—‹|*
  6393.   theError:   OSErr;°dONLNdâ€ÊÜ*
  6394.   theVers:    INTEGER;°dONLNd†ÂÜ*
  6395.   NoGaps:     BOOLEAN;°dONLNd∑˘1*BEGIN°dONLNdΩw*
  6396.   GetPort(oldPort);°dONLNd—
  6397. 
  6398. *
  6399. 1  thePrRec := THPrint(NewHandle(SIZEOF(TPrint)));°dONLNd"E*
  6400.       PrOpen;°dONLNd
  6401. !,≥*
  6402.   IF PrError = noErr THEN BEGIN°dONLNd-+6ü*
  6403.     PrintDefault(thePrRec);°dONLNdI?J—*%    IF NOT PrStlDialog(thePrRec) THEN°dONLNdoITü*
  6404.       PrSetError(iPrAbort);°dONLNdãS^—*
  6405. %    IF NOT PrJobDialog(thePrRec) THEN°dONLNd±]hü*
  6406.       PrSetError(iPrAbort);°dONLNdÕq|Ö*I    (* First, lock the handle down so we can do a cool with statement. *)°dONLNd{ܧ*
  6407.     HLock(Handle(thePrRec));°dONLNd4Öêü*
  6408.     IF PrError = noErr THEN°dONLNdPèö§*
  6409.     WITH thePrRec^^ DO BEGIN°dONLNdmô§ä*
  6410. J      (* Okay, now get device dependent.  We only want to do this if we *)°dONLNd∏£Æä*
  6411. J      (* know the selected printer driver supports it.                  *)°dONLNd≠∏*
  6412. 2      IF (HiByte(prStl.wDev) = bDevImageWriter) OR°dONLNd6∑¬5*
  6413. 9      (HiByte(prStl.wDev) = bDevImageWriterLQ) THEN BEGIN°dONLNdpÀ÷g*C        (* Now remember the state of the nogaps option.          *)°dONLNd¥’‡Í*
  6414. *        NoGaps := BitTst(@prStl.wDev, 11);°dONLNdflÈÙÖ*I        (* If NoGaps was selected, then turn it off until we PrOpenDoc.*)°dONLNd)Û˛
  6415. *
  6416. 1        IF (NoGaps) THEN BitClr(@prStl.wDev, 11);°dONLNd[Ö*I        (* If we're on the LQ driver, we need to copy the wDev into the*)°dONLNd•Ö*
  6417. I        (* PrintX array, or the LQ driver won't notice that it changed.*)°dONLNdÔ&0*
  6418. 8        IF (HiByte(prStl.wDev) = bDevImageWriterLQ) THEN°dONLNd(%0¬*
  6419. "          PrintX[2] := prStl.wDev;°dONLNdK/:J*
  6420.  
  6421.       END;°dONLNdV9D@*
  6422.     END;°dONLNd_CNÆ*
  6423.     HUnlock(Handle(thePrRec));°dONLNd~Wb∏*     (* Now open the document. *)°dONLNdüal*
  6424. /    thePrPort := PrOpenDoc(thePrRec, NIL, NIL);°dONLNdœuÄÖ*I    (* Now we need to see if the NoGaps option was selected. If it was *)°dONLNdäÖ*
  6425. I    (* then we turned it off before calling PrOpenDoc, so we need to   *)°dONLNdcâîÖ*
  6426. I    (* turn it back on. If wasn't selected, we won't do anything.      *) ¡4¡˘
  6427. *&12)
  6428.  of 14(÷mPR 515 - Printing Manager Q&As+5M.PR.PrtMgr.Q&AsˇJ◊#ˇ ˇˇˇˇ#◊ 
  6429. IR,Times
  6430. .+Z-Developer Support Center(-€September 1993 /X/,
  6431. Courier
  6432.     °dONLNd<(»(DZ    HLock(Handle(thePrRec));°dONLNd'<2»*
  6433.     WITH thePrRec^^ DO BEGIN°dONLNd:1<<õ*
  6434.       IF NoGaps AND°dONLNdN;<F1*
  6435. 1        (HiByte(prStl.wDev) = bDevImageWriter) OR°dONLNdÄE<Pc*
  6436. ;        (HiByte(prStl.wDev) = bDevImageWriterLQ) THEN BEGIN°dONLNdºO<Z*
  6437. -        (* Turn it on for the ImageWriter. *)°dONLNdÍY<d‹*
  6438.          BitSet(@prStl.wDev, 11);°dONLNd m<x6*2        (* Copy it over for the ImageWriter LQ. *)°dONLNd>w<ÇT*
  6439. 8        IF (HiByte(prStl.wDev) = bDevImageWriterLQ) THEN°dONLNdwÅ<åÊ*
  6440. "          PrintX[2] := prStl.wDev;°dONLNdöã<ñn*
  6441.  
  6442.       END;°dONLNd•ï<†d*
  6443.     END;°dONLNdÆü<™“*
  6444.     HUnlock(Handle(thePrRec));°dONLNdÕ©<¥·*
  6445. !    IF PrError = noErr THEN BEGIN°dONLNdÔ≥<æ·*
  6446. !      PrOpenPage(thePrPort, NIL);°dONLNdΩ<»Î*
  6447. #      IF PrError = noErr THEN BEGIN°dONLNd5«<“*
  6448. +        DrawStuff(thePrRec^^.prInfo.rPage);°dONLNda—<‹n*
  6449.  
  6450.       END;°dONLNdl€<ÊÕ*
  6451.       PrClosePage(thePrPort);°dONLNdäÂ<d*
  6452.     END;°dONLNdìÔ<˙æ*
  6453.     PrCloseDoc(thePrPort);°dONLNdÆ˘<ö*
  6454. F    IF (thePrRec^^.prJob.bJDocLoop = bSpoolLoop) and (PrError = noErr)°dONLNdˆ<Y*
  6455. 9      THEN PrPicFile(thePrRec, NIL, NIL, NIL, theStatus);°dONLNd0
  6456. <Z*
  6457.   END;°dONLNd7<"n*
  6458.  
  6459.   PrClose;°dONLNdB+<6·*!  DisposHandle(Handle(thePrRec));°dONLNdd5<@õ*
  6460.   SetPort(oldPort);°dONLNdx?<JP*
  6461. END;°dONLNd}S<^U*BEGIN°dONLNdÉ]<hï*
  6462. E  InitGraf(@thePort);                          {initialize QuickDraw}°dONLNd…g<r§*
  6463. H  InitFonts;                                   {initialize Font Manager}°dONLNdq<|h*
  6464. <  FlushEvents(everyEvent, 0); {call OS Event Mgr to discard}°dONLNdO{<Ü;*
  6465. 3                              {any previous events}°dONLNdÉÖ<êÆ*
  6466. J  InitWindows;                                 {initialize Window Manager}°dONLNdŒè<ö§*
  6467. H  InitMenus;                                   {initialize Menu Manager}°dONLNdô<§ê*
  6468. D  TEInit;                                      {initialize TextEdit}°dONLNd\£<Æï*
  6469. E  InitDialogs(NIL);                       {initialize Dialog Manager}°dONLNd¢≠<∏≥*
  6470. K  InitCursor;            {call QuickDraw to make cursor (pointer) an arrow}°dONLNdÓ¡<Ã}*
  6471.   PrintStuff;°dONLNd¸À<÷P*
  6472. END.
  6473. °dONLNdÌ<¸Ñ*&1Update Macintosh color table if printing in color
  6474. °dONLNd3¸<û* Date Written:  5/3/89°dONLNdI<´* Last reviewed:  6/14/93°dONLNda <,ú*GI’m having trouble printing in color. When I copy a color image from a °dONLNd® ú,˛(H∫Macintosh offscreen°dONLNdº,<8π(TZUpixmap to the printer, I get a black piece of paper. If I draw directly it comes out °dONLNd,π8˛(T◊
  6475. fine. What am°dONLNd8<DÖ(`ZI doing wrong?°dONLNd.D<PN* ___°dONLNd2\<hÉ*EWhen you built your offscreen port and copied the color table from a °dONLNdw\Éh˛(ѰGDevice, did you change°dONLNdèh<tõ(êZLthe color table to reflect that the color table is now part of a pixmap? In °dONLNd€hõt˛(êπa GDevice the color°dONLNdÔt<ÄQ(úZ=table’s value field is zero for all entries, but in a pixmap °dONLNd,tQIJ(úo$the value field represents the index ¡X¡
  6476. (÷ZPR 515 - Printing Manager Q&As(÷˙13)
  6477.  of 14(ÏZM.PR.PrtMgr.Q&Asˇ™◊#ˇ ˇˇˇˇ#◊ 
  6478. IR,Times
  6479. .+6-Macintosh Technical Notes /4/˘
  6480. °dONLNd)π*%value of each color in the table. If °dONLNd%π)⁄)°;the color table has not been converted, printing won’t work°dONLNda)5D(Q6    properly. ¡4¡˘
  6481. (÷614)
  6482.  of 14(÷mPR 515 - Printing Manager Q&As+5M.PR.PrtMgr.Q&Asˇ◊#ˇ ˇˇˇˇ#◊†Ç 
  6483. /ZÅ#
  6484.     0Ià:µú9"{    ˇˇˇˇˇˇˇˇ#†ƒ°d
  6485. ONLNf˛†å°d1drw2…-·_ġˇˇˇˇˇè°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˙ó@†ò,Times
  6486. .R…R…+]BNew Technical Notes†ô°ddrw2:°„†ó°d1drw2eÙġˇˇˇˇˇP°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚ÄE¿†ò
  6487. ({ïDeveloper Support†ô°ddrw2:°„†ó°d`drw2-ÔˇˇˇˇˇˇKÔ- Z  ffZ°d1drw2 ¿˙ÈˇˇˇˇˇˇK°ñ x°ddrw2:°ddrw2:$°d4drw2:0°öˇÙĆò
  6488. 0(UÔ†ô°ddrw2:°„†ó°d1drw2ÔÊ˙ˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:    °öˇ˝Ä†ò
  6489.     +&    ®†ô°ddrw2:°„†ó°d1drw2Â-¯yˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚Ä%†ò
  6490. (Z\    Macintosh†ô°ddrw2:°„†ó†ç°ddrw2D†É
  6491. IR.°dONLNdn<Å.(õZPR 520 - PrintMonitor Q&As
  6492. °dONLNdÄ<ès*Printing
  6493. °dONLNd%õ<ßt* Revised by:°dONLNd1õÑߡ)HDeveloper Support Center°dONLNdJõ±ß˛(√œSeptember 1993°dONLNdYß<≥q(œZ Written by:°dONLNdeßÑ≥ˇ)HDeveloper Support Center°dONLNd~ßæ≥˛(œ‹ October 1990°dONLNdãø<À⁄(ÁZThis Technical Note contains a °dONLNd™ø⁄À˛)û9collection of Q&As relating to a specific topic—questions°dONLNd‰À<◊†(ÛZGyou’ve sent the Developer Support Center (DSC) along with answers from °dONLNd+À†◊˛(Ûæthe DSC engineers.°dONLNd>◊<„u(ˇZ
  6494. While DSC °dONLNdH◊u„˛)9Lengineers have checked the Q&A content for accuracy, the Q&A Technical Notes°dONLNdï„<Ôq( Z don’t have °dONLNd†„qÔ˛)5Qthe editing and organization of other Technical Notes. The Q&A function is to get°dONLNdÚÔ<˚Ÿ(Znew technical information and °dONLNdÔŸ˚˛)ù6updates to you quickly, saving the polish for when the°dONLNdG˚<(#Z,information migrates into reference manuals.°dONLNdt<k*:Q&As are now included with Technical Notes to make access °dONLNdÆk˛(;âto technical updates easier for°dONLNdŒ<+.(GZ/you. If you have comments or suggestions about °dONLNd˝.+˛)Ú*Q&A content or distribution, please let us°dONLNd(+<7\(SZknow °dONLNd-+\7˛) Iby sending an AppleLink to DEVFEEDBACK. Apple Partners may send technical°dONLNdw7<Ci(_Z9questions about Q&A content to DEVSUPPORT for resolution.°dONLNd±O<[·* New Q&As in this Technical Note:°dONLNd“[<g4* 2Determining whether background printing is enabled íXí
  6495. °dONLNdå<õù*42Determining whether background printing is enabled
  6496. °dONLNd8õ<ßô* 62755 MD JM dy 1°dONLNdIß<≥§* Date Written:  1/20/93°dONLNd`≥<ø´* Last reviewed:  4/26/93°dONLNdxÀ<◊Æ*OHow can I tell whether background printing is enabled for the selected printer?°dONLNd»◊<„N* ___°dONLNdÃÔ<˚N*7There’s no procedure to determine whether the user has °dONLNdÔN˚˛(l"picked background printing because°dONLNd&˚<"(#Z0that’s not a standard Macintosh system software °dONLNdV˚"˛)Ê-feature. Where it’s done, it’s implemented on°dONLNdÑ<¨(/ZSa driver-by-driver basis, and each printer driver keeps track of it in a different °dONLNd◊¨˛(/ way. Apple does°dONLNdÁ<«(;ZPit one way, Hewlett-Packard might do it another way, GCC a third way, and so on.°dONLNd8+<7á*DSince we don’t actually know how it’s done, and since Apple doesn’t °dONLNd|+á7˛(S•guarantee its drivers will°dONLNdó7<C‹(_ZWdo it the same way in the future as they do now, we have no information to give you on °dONLNdÓ7‹C˛(_˙how to°dONLNdıC<O,(kZ3determine this. Sorry to be the bearer of bad news.
  6497. °dONLNd)g<vR*')Location for spool files under System 7.0
  6498. °dONLNdSv<Ç™* Date Written:  12/18/90°dONLNdkÇ<é•* Last reviewed:  8/1/92 ¡X¡
  6499. *,PR 520 - Print Monitor Q&As(÷1) of 5(ÏZM.PR.PrtMon.Q&Asˇ°¿Ù%%DSIDICT:_cv
  6500. currentdict /bu known {bu}if
  6501. userdict /_cv known not{userdict /_cv 30 dict put}if
  6502. _cv begin
  6503. /bdf{bind def}bind def
  6504. currentscreen/cs exch def/ca exch def/cf exch def
  6505. /setcmykcolor where{/setcmykcolor get /cvcmyk exch def}{/cvcmyk{1 sub 4 1 roll 3{3 index add neg dup 0 lt{pop 0}if 3 1 roll}repeat setrgbcolor pop}bdf }ifelse
  6506. /ss{//cf //ca //cs setscreen}bdf
  6507. /stg{ss setgray}bdf
  6508. /strgb{ss setrgbcolor}bdf
  6509. /stcmyk{ss cvcmyk}bdf
  6510. /min1{dup 0 eq{pop 1}if}bdf
  6511. end
  6512. currentdict /bn known {bn}if
  6513. †øö◊#ˇ ˇˇˇˇ#◊ 
  6514. IR,Times
  6515. .+6-Macintosh Technical Notes /4/˘
  6516. °dONLNd)5≠*$XIs there a recommended location for printer driver writers to put their own spool files?°dONLNdY5A** ___°dONLNd]MY*7Place it in the “PrintMonitor Documents” folder within °dONLNdîMY⁄(u:'a “personal spool” folder. PrintMonitor°dONLNdºYeí(Å6Uwill ignore other folders and it will delete its spool file when it was done with it.°dONLNdq}9*?The biggest advantage with this approach is that all the spool °dONLNdQq9}⁄(ôW"files end up in the same location,°dONLNdt}â(•68which is probably the best solution for the native user.°dONLNd≠ï°Ã*_There are a few cases when the folder might not be present (such as if the user has deleted it °dONLNd ïð⁄(ΩÍfor°dONLNd°≠ú(…6Rsome reason). Therefore, you should check to make sure that the folder is present °dONLNdb°ú≠⁄(…∫
  6517. before trying°dONLNdp≠π®(’6Uto add a file to it. If it is not present, be sure to create it with the exact name; °dONLNd≈≠®π⁄(’Δ
  6518. otherwise,°dONLNd–π≈ê(·6PPrintMonitor will not be able to find it and will create a second folder with a °dONLNd πê≈⁄(·Ædifferent name,°dONLNd0≈—'(Ì66possibly confusing the native user. Folder management °dONLNdf≈'—⁄(ÌE&is relatively straightforward with the°dONLNdç—›œ(˘6$addition of the “Folder Manager” to °dONLNd±—œ›Ü)∑"System 7.0. The Finder chapter in °dONLNd”—Ü›⁄)∑Inside Macintosh°dONLNd‰›ÈÔ(6.Volume VI contains the details about using it.
  6519. °dONLNdá*'4Determining whether background printing is turned on
  6520. °dONLNdHz* Date Written:  2/5/92°dONLNd^(Å* Last reviewed:  8/1/92°dONLNdu4@Ω*SI need to know whether the currently chosen printer driver—that I’m about to print °dONLNd»4Ω@⁄(\€to—is°dONLNdŒ@LÛ(h6)going to be doing background printing or °dONLNd˜@ÛL⁄)€-not. The user interface of our application is°dONLNd%LX.(t6:somewhat different, depending on this. Currently, I check °dONLNd_L.X⁄(tL%the driver’s file type to see whether°dONLNdÖXdh(Ä6it’s network- or °dONLNdñXhd⁄)PIlocal-attached, generalizing “network = LaserWriter = background capable”°dONLNd‡dp(å64and “direct = ImageWriter = foreground only,” but I °dONLNddp⁄)˙)know this isn’t always correct, because a°dONLNd>p|“(ò6^variety of direct-connect printer drivers now support background printing. What I really need °dONLNdúp“|⁄(òis°dONLNdü|àj(§6Ha way to check specifically for background printing being turned on. Is °dONLNdÁ|jà÷(§àthere a safe and driver°dONLNd˛|÷à⁄)l-°dONLNdˇàî´(∞6independent way to check this?°dONLNdî†** ___°dONLNd"¨∏√*#No, there’s absolutely no safe and °dONLNdE¨√∏⁄)´6driver-independent way to do this. Although Apple uses°dONLNd|∏ƒ»(‡6]PrintMonitor for all background printing, it’s not designed for third-party products to hook °dONLNdŸ∏»ƒ⁄(‡Êinto°dONLNdfiƒ–<(Ï6it. The °dONLNdʃ<–⁄)$R“background printing” internals aren’t documented because changing that outside an°dONLNd9–‹T(¯6Findividual printer driver may not give the driver all the information °dONLNd–T‹⁄(¯rit needs to correctly print in°dONLNdû‹Ë1(6<the background. Also, third parties have to implement their °dONLNd⁄‹1ËF(Oown°dONLNd›‹FËI) °dONLNdfi‹IË⁄)background printing schemes,°dONLNd˚ËÙ<(6:and there’s absolutely no way to know how they’re storing °dONLNd    5Ë<Ù⁄(Zthe choice on whether or not to°dONLNd    UÙä(6print in the background.°dONLNd    n Æ*VIf your user interface is substantially different, you may need to require your users °dONLNd    ƒ Æ⁄(4à   to enable°dONLNd    Œ$†(@6background printing in your °dONLNd    Í†$⁄)àCapplication as well as in the Chooser. This isn’t exactly friendly,°dONLNd
  6521. .$0Ç(L6Lbut since there’s no mechanism for applications to communicate with printer °dONLNd
  6522. z$Ç0⁄(L†drivers to find out°dONLNd
  6523. é0<<(X6=about background printing, it’s pretty much your only choice.°dONLNd
  6524. ÃHT∂*[You’re right, checking a driver’s file type to see whether it’s network- or local-attached °dONLNd 'H∂T⁄(p‘is not a°dONLNd 0T`%(|68good solution. StyleWriters and LaserWriter LS printers °dONLNd hT%`⁄(|C%print in the background but don’t use°dONLNd é`lƒ(à6Ya network. Some third-party laser printers support AppleTalk but not background printing. ¡4¡˘
  6525. *N2) of 5(÷{PR 520 - Print Monitor Q&As+%M.PR.PrtMon.Q&Asˇl◊#ˇ ˇˇˇˇ#◊ 
  6526. IR,Times
  6527. .+Z-Developer Support Center(-€September 1993 /X/
  6528. °dONLNd<,ë(HZ0Turning Macintosh background printing on and off
  6529. °dONLNd1,<8§* Date Written:  3/25/92°dONLNdH8<D´* Last reviewed:  6/14/93°dONLNd`P<\Ü*ESomeone has requested that we do an extension for our application to °dONLNd•PÜ\˛(x§turn background printing°dONLNdæ\<h
  6530. (ÑZ+on and off. Can you tell me how to do this?°dONLNdÍh<tN* ___°dONLNdÓÄ<å¬*IUnfortunately, DTS can’t tell you how to turn background printing on and °dONLNd7Ĭå˛(®‡ off, for the°dONLNdDå<òî(¥Zfollowing reasons:°dONLNdW§<∞q* 1. Apple’s °dONLNdb§q∞˛)5Rmechanism for background printing (PrintMonitor) is at this time only available to°dONLNdµ∞<ºY(ÿZ;Apple’s printer drivers. How Apple’s printer drivers store °dONLNd∞Yº˛(ÿw!the background printing choice is°dONLNdº<»›(‰ZYprivate because Engineering has changed it in the past and might need to change it again.°dONLNdl‘<‡ö*M2. Since all third-party printer drivers that do background printing have to °dONLNdπ‘ö‡˛(¸∏do it their own way,°dONLNdŒ‡<ÏA(Z6they all have to find their own ways of recording the °dONLNd‡AÏ˛(_%“background printing” choice, such as°dONLNd*Ï<¯∑(Zstoring the information in °dONLNdEÏ∑¯˛){Cresources like the PAPA resource. Since there are no guidelines for°dONLNdâ¯<©( Zrecording background °dONLNdû¯©˛)m?printing options, DTS cannot recommend a method which will work°dONLNdfi<á(,Zwith all drivers.°dONLNd<(R*For °dONLNdÙR(˛)Sthese reasons, and to avoid possible Human Interface conflicts, background printing°dONLNdH(<4»(PZ!control is best left to the user.
  6531. °dONLNdjL<[Ü*'-Macintosh PicComments and background printing
  6532. °dONLNdò[<gû* Date Written:  5/3/89°dONLNdÆg<s´* Last reviewed:  6/14/93°dONLNdΔ<ã◊* My Macintosh application prints °dONLNdÊ◊ã˛)õ<fine when Background Printing is disabled, but doesn’t print°dONLNd#ã<ów(≥Z?or prints blank pages when Background Printing is enabled. Why?°dONLNdcó<£N* ___°dONLNdgØ<ªQ*The °dONLNdkØQª˛)WPrinting Manager gets execution time by replacing the grafProcs of the Printing Manager°dONLNd√ª<«\(„Z;GrafPort (returned from the PrOpenDoc call). This GrafPort °dONLNd˛ª\«˛(„z!is created by the PrOpenDoc call,°dONLNd «<”â(ÔZEand is reinitialized by every call to PrOpenPage. On the LaserWriter °dONLNde«â”˛(Ôßdriver with Background°dONLNd|”<flZ(˚Z<Printing enabled, this reinitialization causes the clipping °dONLNd∏”Zfl˛(˚xregion of the port to be set to°dONLNdÿfl<ÎÑ(ZD(0,0,0,0). On the next call to StdLine or StdText, for example, the °dONLNdflÑβ(¢Printing Manager notices°dONLNd5Î<˜(Z+the zeroed clipping region, and sets it to °dONLNd`Θ˛)«4the rectangle specified by prInfo.rPage in the print°dONLNdï˜<(ZTrecord. If your application prints its documents with PostScript using PicComments, °dONLNdȘ˛(the°dONLNdÌ<ã(+ZHPrinting Manager never gets a chance to define the clipping region. All °dONLNd5ã˛(+©of your PostScript code°dONLNdM<e(7Z=is sent to the LaserWriter and executed, but the results are °dONLNdäe˛(7Éclipped to (0,0,0,0). To work°dONLNd®<'(CZ0around this problem, you must call at least one °dONLNdÿ'˛)fl-Quickdraw drawing routine at the beginning of°dONLNd    '<3(OZ,each page. The following is frequently used:,
  6533. Courier
  6534.     °dONLNd    3?<J†*    PrOpenPage(...);°dONLNd    HI<T√*
  6535.     MoveTo(-32000, -32000);°dONLNd    dS<^á*
  6536.     Line(0, 0);°dONLNd    t]<h»*
  6537.     { PostScript code here }°dONLNd    ëg<r•*
  6538.     PrClosePage(...);
  6539. °dONLNd    ß}<â˝*)The MoveTo is needed so that the line is °dONLNd    –}˝â˛)¡4drawn outside of the imageable area of the page, and°dONLNd
  6540. â<ïç(±Zthus is invisible. °dONLNd
  6541. âçï˛)QLThe Line call calls the Printing Manager’s version of the StdLine procedure, ¡X¡
  6542. (÷ZPR 520 - Print Monitor Q&As(÷ˇ3) of 5 (ÏZM.PR.PrtMon.Q&Asˇ∂◊#ˇ ˇˇˇˇ#◊ 
  6543. IR,Times
  6544. .+6-Macintosh Technical Notes /4/˘
  6545. °dONLNd)n*which defines the °dONLNdn)⁄)VLclipping region for the port. All subsequent PostScript code will be clipped°dONLNd_)5 (Q68correctly. Since PrOpenPage resets the clipping region, °dONLNdó) 5⁄(Q>#the MoveTo/Line combination must be°dONLNdª5A¿(]6#done after each call to PrOpenPage.
  6546. °dONLNdflYh*'!SetOrigin and background printing
  6547. °dONLNdhtz* Date Written:  1/1/90°dONLNdtÄá* Last reviewed:  6/14/93°dONLNd/åò]*I have noticed °dONLNd>å]ò⁄)EOPostScript graphics printing in different locations depending on whether or not°dONLNdéò§[(¿6BBackground printing is enabled on the Macintosh. What causes this?°dONLNd—§∞** ___°dONLNd’º» */In LaserWriter 4.0 - 5.2, SetOrigin is handled °dONLNdº »⁄)Ù'differently when Background printing is°dONLNd,»‘@(6=enabled. The method used by these drivers is described below:°dONLNdj‡Ïh*CBackground Printing DISABLED: The application calls SetOrigin, and °dONLNd≠‡hÏ⁄(ÜQuickDraw responds to°dONLNd√ϯ,(6:the call by adjusting the portRect of the Print Manager’s °dONLNd˝Ï,¯⁄(J"GrafPort. Since SetOrigin does not°dONLNd ¯Δ( 6Scause any grafProcs to run, the Printing Manager doesn’t see this change until the °dONLNds¯Δ⁄( ‰next°dONLNdxÄ(,6BQuickDraw drawing operation such as DrawString or LineTo. At that °dONLNd∫Ä⁄(,ûtime, the Printing°dONLNdÕj(86Manager notices °dONLNd›j⁄)RJthe change in the portRect, and updates its internal origin. All QuickDraw°dONLNd((·(D6&graphics are now localized to the new °dONLNdN·(⁄)…1origin. All PostScript graphics will also get the°dONLNdÄ(4§(P6localization to the new origin.°dONLNd†@L«*NBackground Printing ENABLED: Because QuickDraw is playing back a picture that °dONLNdÓ@«L⁄(hÂwas°dONLNdÚLXS(t6Espooled earlier, it handles calls to SetOrigin a little differently. °dONLNd7LSX⁄(tqWhen the SetOrigin call is°dONLNdRXd)(Ä67encountered in a DrawPicture call, the portRect of the °dONLNdâX)d⁄(ÄG!GrafPort is NOT updated. Instead,°dONLNd´dpÃ(å6VQuickDraw keeps the current origin cached, and offsets each graphic on the fly. Since °dONLNddÃp⁄(åÍthe°dONLNdp|≠(ò6portRect was not modified, the °dONLNd$p≠|⁄)ï>Printing Manager does not see the SetOrigin call. Although all°dONLNdc|àπ(§6TQuickDraw objects are still localized correctly (by QuickDraw), PostScript graphics °dONLNd∑|πà⁄(§◊do not°dONLNdæàîL(∞6?move to the new origin. Instead, the application localizes the °dONLNd˝àLî⁄(∞jcoordinates of its PostScript°dONLNdî†b(º6graphics. You °dONLNd)îb†÷)JGcould also use the technique documented in the Technical Note “Position°dONLNdpî÷†⁄(ºÙ-°dONLNdq†¨è(»6Independent PostScript.”°dONLNdä∏ƒP*@The implementation of the SetOrigin (IM I:166) and ClipRect (IM °dONLNd ∏Pƒ⁄(‡nI:167) calls has been revised°dONLNd˃–O(Ï6Cin LaserWriter 6.0. This is a general description of those changes:°dONLNd,‹ËÃ*VLaserWriter 6.0: Both QuickDraw and PostScript coordinates are offset with respect to °dONLNdÇ‹ÃË⁄(Íthe°dONLNdÜËÙw(6Korigin set by SetOrigin. The driver now inserts a picture comment into the °dONLNd—ËwÙ⁄(ïspool file so that the°dONLNdËÙQ(6@Print Monitor knows that the origin was changed during spooling.°dONLNd    ) ˙*0Since applications must support versions of the °dONLNd    Y ˙⁄)‚.LaserWriter driver other than 6.0, they should°dONLNd    à$k(@6Dstill use the method described in this Tech Note to make sure their °dONLNd    Ãk$÷(@âPostScript is position°dONLNd    ‚÷$⁄)k-°dONLNd    „$0U(L6 independent.°dONLNd    <H9*X-Ref:°dONLNd    ˜HTR* >DTS Macintosh Technical Note “Position-Independent PostScript”
  6548. °dONLNd
  6549. 6l{C*'-Macintosh spool file formats aren’t available
  6550. °dONLNd
  6551. d{áz* Date Written:  1/1/90°dONLNd
  6552. záìÅ* Last reviewed:  8/1/92 ¡4¡˘
  6553. *'4) of 5(÷{PR 520 - Print Monitor Q&As+%M.PR.PrtMon.Q&AsˇX◊#ˇ ˇˇˇˇ#◊ 
  6554. IR,Times
  6555. .+Z-Developer Support Center(-€September 1993 /X/
  6556. °dONLNd)<5Ø(QZMWhat is file format of Macintosh Printing Manager and LaserShare spool files?°dONLNdN5<AN* ___°dONLNdRM<Yù*OUnfortunately, the formats for these files are not currently available, and it °dONLNd°MùY˛(uªis doubtful that they°dONLNd∑Y<eÄ(ÅZ@will be made available in the future. Whenever new features are °dONLNd˜YÄe˛(Åûadded to LaserShare, the°dONLNde<q‰(çZ$Printing Manager, or other parts of °dONLNd4e‰q˛)®8the Macintosh toolbox, it’s not uncommon for these spool°dONLNdmq<}«(ôZXfile formats to be affected. If the file format were published, and essentially frozen, °dONLNd≈q«}˛(ôÂ it would be°dONLNd—}<â(•Z,much harder for engineering to add features. ¡X¡
  6557. (÷ZPR 520 - Print Monitor Q&As(÷ˇ5) of 5 (ÏZM.PR.PrtMon.Q&Asˇå◊#ˇ ˇˇˇˇ#◊†Ç 
  6558. /ZÅ#
  6559.     0Ià:µú9"{    ˇˇˇˇˇˇˇˇ#†ƒ°d
  6560. ONLNf˛†å°d1drw2…-·_ġˇˇˇˇˇè°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˙ó@†ò,Times
  6561. .R…R…+]BNew Technical Notes†ô°ddrw2:°„†ó°d1drw2eÙġˇˇˇˇˇP°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚ÄE¿†ò
  6562. ({ïDeveloper Support†ô°ddrw2:°„†ó°d`drw2-ÔˇˇˇˇˇˇKÔ- Z  ffZ°d1drw2 ¿˙ÈˇˇˇˇˇˇK°ñ x°ddrw2:°ddrw2:$°d4drw2:0°öˇÙĆò
  6563. 0(UÔ†ô°ddrw2:°„†ó°d1drw2ÔÊ˙ˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:    °öˇ˝Ä†ò
  6564.     +&    ®†ô°ddrw2:°„†ó°d1drw2Â-¯yˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚Ä%†ò
  6565. (Z\    Macintosh†ô°ddrw2:°„†ó†ç°ddrw2D†É
  6566. IR.°dONLNdn<Åã(õZ#PR 525 - QuickDraw GX Printing Q&As
  6567. °dONLNd$Ä<ès*Printing
  6568. °dONLNd.õ<ßt* Revised by:°dONLNd:õÑߡ)HDeveloper Support Center°dONLNdSõ±ß˛(√œSeptember 1993°dONLNdbß<≥q(œZ Written by:°dONLNdnßÑ≥ˇ)HDeveloper Support Center°dONLNdáßæ≥˛(œ‹ October 1990°dONLNdîø<À⁄(ÁZThis Technical Note contains a °dONLNd≥ø⁄À˛)û9collection of Q&As relating to a specific topic—questions°dONLNdÌÀ<◊†(ÛZGyou’ve sent the Developer Support Center (DSC) along with answers from °dONLNd4À†◊˛(Ûæthe DSC engineers.°dONLNdG◊<„u(ˇZ
  6569. While DSC °dONLNdQ◊u„˛)9Lengineers have checked the Q&A content for accuracy, the Q&A Technical Notes°dONLNdû„<Ôq( Z don’t have °dONLNd©„qÔ˛)5Qthe editing and organization of other Technical Notes. The Q&A function is to get°dONLNd˚Ô<˚Ÿ(Znew technical information and °dONLNdÔŸ˚˛)ù6updates to you quickly, saving the polish for when the°dONLNdP˚<(#Z,information migrates into reference manuals.°dONLNd}<k*:Q&As are now included with Technical Notes to make access °dONLNd∑k˛(;âto technical updates easier for°dONLNd◊<+.(GZ/you. If you have comments or suggestions about °dONLNd.+˛)Ú*Q&A content or distribution, please let us°dONLNd1+<7\(SZknow °dONLNd6+\7˛) Iby sending an AppleLink to DEVFEEDBACK. Apple Partners may send technical°dONLNdÄ7<Ci(_Z9questions about Q&A content to DEVSUPPORT for resolution.°dONLNd∫O<[Ω*New Q&As for this month:°dONLNd”[<g7* 2QuickDraw GX printing extensions and creator types°dONLNdg<sÎ* !NewMessageGlobals and global data°dONLNd(s<v* >QuickDraw GX LaserWriter driver produces “portable” PostScript°dONLNdg<ã"* -QuickDraw GX PostScript Level 2 features used°dONLNdïã<ó* -QuickDraw GX printer drivers and color option ¬X¬
  6570. °dONLNd√º<Àû*42QuickDraw GX printing extensions and creator types
  6571. °dONLNdˆÀ<◊°* Date Written:   5/3/93°dONLNd
  6572. ◊<„¢* Last reviewed: 7/2/93°dONLNd#Ô<˚T*7A QuickDraw GX printing extension I’ve already written °dONLNdZÔT˚˛(r!works fine, but when I install my°dONLNd|˚<(#Z1latest creation, it doesn’t show up in the print °dONLNd≠˚˛)·+dialog—only my old printing extension does.°dONLNdŸ<÷(/ZSBoth extensions are the same except for a few lines of code in their gxDespoolPage °dONLNd,÷˛(/Ùmessage°dONLNd4<√(;Zoverrides. What’s going on?°dONLNdP<+N* ___°dONLNdT7<Cfi*UYour printing extensions shouldn’t have the same creator type. QuickDraw GX requires °dONLNd©7fiC˛(_¸unique°dONLNd∞C<OA(kZ8creator types for drivers and printing extensions, just °dONLNdËCAO˛(k_&as the Finder does for applications. A°dONLNdO<[ß(wZFcreator type must be unique because QuickDraw GX uses it to build its °dONLNdUOß[˛(w≈chain of message°dONLNdf[<g(ÉZ.handlers. If two printing extensions have the °dONLNdî[g˛)÷/same creator, there’s no way to determine which°dONLNdƒg<sZ(èZ:is which in the chain. You can register creator types for °dONLNd˛gZs˛(èx!your printer drivers and printing°dONLNd s<•(õZDextensions with the Developer Support Center (AppleLink DEVSUPPORT). ¡X¡
  6573. *;#PR 525 - QuickDraw GX Printing Q&As(÷1) of 3(ÏZM.PR.GDGXprt.Q&Asˇ°¿Ù%%DSIDICT:_cv
  6574. currentdict /bu known {bu}if
  6575. userdict /_cv known not{userdict /_cv 30 dict put}if
  6576. _cv begin
  6577. /bdf{bind def}bind def
  6578. currentscreen/cs exch def/ca exch def/cf exch def
  6579. /setcmykcolor where{/setcmykcolor get /cvcmyk exch def}{/cvcmyk{1 sub 4 1 roll 3{3 index add neg dup 0 lt{pop 0}if 3 1 roll}repeat setrgbcolor pop}bdf }ifelse
  6580. /ss{//cf //ca //cs setscreen}bdf
  6581. /stg{ss setgray}bdf
  6582. /strgb{ss setrgbcolor}bdf
  6583. /stcmyk{ss cvcmyk}bdf
  6584. /min1{dup 0 eq{pop 1}if}bdf
  6585. end
  6586. currentdict /bn known {bn}if
  6587. †ø
  6588. å◊#ˇ ˇˇˇˇ#◊ 
  6589. IR,Times
  6590. .+6-Macintosh Technical Notes /4/˘
  6591. °dONLNd,*!NewMessageGlobals and global data
  6592. °dONLNd",8z* Date Written:  2/1/93°dONLNd88D~* Last reviewed: 7/2/93°dONLNdNP\§*LWhy can’t I get NewMessageGlobals to work in my gxInitialize message for my °dONLNdöP§\⁄(x¬    QuickDraw°dONLNd§\h∞(Ñ6ZGX printing extension? The global data I try to initialize isn’t being accessed correctly.°dONLNdˇht** ___°dONLNdÄåa*You shouldn’t °dONLNdÄaå⁄)IGcall NewMessageGlobals from any routine in which you access your global°dONLNdYåò2(¥6data. °dONLNd_å2ò⁄)VOtherwise, because of optimization that your compiler may perform, the data references°dONLNd∂ò§(¿63can be invalid. Instead, use an approach like this:,
  6593. Courier
  6594.     °dONLNdÍ∞ªï*extern long A5Size(void);°dONLNd∫≈ü*
  6595. extern void A5Init(void *);°dONLNd ƒœÆ*
  6596. typedef    struct GlobalType {°dONLNd?ŒŸ§*
  6597.     StringHandle    aString;°dONLNd\ÿ„Y*
  6598.  
  6599. } GlobalType;°dONLNdj‚Ìê*
  6600. GlobalType    myGlobals;°dONLNdɈN*>/* This routine sets the initial values of our global data. */°dONLNd¬ Ü*
  6601. OSErr InitGlobalData()°dONLNdŸ
  6602. *
  6603. {°dONLNd€m*
  6604.     OSErr    err;°dONLNdÌ)Æ*
  6605.     // Initialize our globals.°dONLNd (3*
  6606. 0    myGlobals.aString = GetString(r_myStringID);°dONLNd=2=Å*
  6607.     err = ResError();°dONLNdS<G*
  6608. 0    if (!err) DetachResource(myGlobals.aString);°dONLNdÑFQc*
  6609.     return err;°dONLNdîP[*
  6610. }°dONLNdñdo*0/* Our override for the gxInitialize message. */°dONLNd«ny|*
  6611. OSErr MyInitialize()°dONLNd‹xÉ*
  6612. {°dONLNdfiÇçm*
  6613.     OSErr    err;°dONLNdåóN*
  6614. >    // Create an A5 world, then go initialize our global data.°dONLNd/ñ°*
  6615. 0    err = NewMessageGlobals(A5Size(), A5Init());°dONLNd`†´—*
  6616. %    if (!err) err = InitGlobalData();°dONLNdÜ™µc*
  6617.     return err;°dONLNdñ¥ø*
  6618. }
  6619. °dONLNdò ÷À*&A detailed explanation of the problem °dONLNdæ À÷⁄)≥4accompanies the Kabooms printing extension sample on°dONLNdÛ÷‚p(˛6the Developer CD.
  6620. °dONLNd˙    ◊*'>QuickDraw GX LaserWriter driver produces “portable” PostScript
  6621. °dONLNdD    Ü* Date Written:  11/17/92°dONLNd\!~* Last reviewed: 7/2/93°dONLNdr-9*.When a QuickDraw GX PostScript printer driver °dONLNd†-9⁄)Í.generates a file, will it work for Level 1 and°dONLNdœ9Eg(a6Level 2 printers?°dONLNd·EQ** ___°dONLNdÂ]i-*The °dONLNdÈ]-i⁄)TLaserWriter driver bundled with QuickDraw GX produces a flavor of PostScript that we°dONLNd>iu+(ë6call °dONLNdCi+u⁄)Y“portable.” This flavor is meant to work on the widest range of printing devices, be they°dONLNdùuÅŒ(ù6'Level 1 or 2, color or black and white. ¡4¡˘
  6622. *92) of 3(÷Q#PR 525 - QuickDraw GX Printing Q&As+GM.PR.QDGXprt.Q&AsˇÙ◊#ˇ ˇˇˇˇ#◊ 
  6623. IR,Times
  6624. .+Z-Developer Support Center(-€September 1993 /X/
  6625. °dONLNd)<8~(TZ-QuickDraw GX PostScript Level 2 features used
  6626. °dONLNd.8<D™* Date Written:  11/17/92°dONLNdFD<P¢* Last reviewed: 7/2/93°dONLNd\\<h⁄*!What PostScript Level 2 features °dONLNd}\⁄h˛)û7does the QuickDraw GX printing mechanism take advantage°dONLNdµh<tK(êZof?°dONLNdπt<ÄN* ___°dONLNdΩå<ò¬*The Level 2 features used °dONLNd◊å¬ò˛)Ü:in QuickDraw GX mostly have to do with patterns, text, and°dONLNdò<§d(¿Zbitmaps:°dONLNd∞<º@*•°dONLNd∞Eº€)    TQuickDraw GX patterns are converted into Level 2 pattern dictionaries when going to °dONLNdq∞€º˛(ÿ˘a Level°dONLNdyºE»Ÿ(‰c[2 printer. The actual PostScript code emitted by the driver differs little with respect to °dONLNd‘ºŸ»˛(‰˜patterns°dONLNd›»E‘±(cwhen going to Level °dONLNdÒ»±‘˛)l>1 or Level 2. However, the procedures defined in the header do°dONLNd0‘E‡*(¸c2something entirely different on a Level 2 printer.°dONLNdc‡<Ï@(Z•°dONLNde‡EÏ1)    /Line layout in QuickDraw GX takes advantage of °dONLNdî‡1Ï˛)Ï&the xshow, yshow, and xyshow operators°dONLNdªÏE¯”(cwhen it makes sense to do so.°dONLNdŸ¯<@( Z•°dONLNd€¯E )    PThe Level 2 rectangle operators are used in Level 2, though this happens in the °dONLNd+¯ ˛( Ë
  6627. procedures°dONLNd6EÉ(,cEdefined in the header rather than in PostScript code from the driver.°dONLNd|<@(8Z•°dONLNd~EÌ)    XOn Level 2 printers, the indexed color spaces are used for printing bitmaps up to eight °dONLNd÷Ì˛(8 bits°dONLNd€E(_(Dcdeep.°dONLNd·(<4@(PZ•°dONLNd„(E4Ç)    BThe plan is to use Level 2 device-independent color when possible.
  6628. °dONLNd&L<[~(wZ-QuickDraw GX printer drivers and color option
  6629. °dONLNdT[<gß* Date Written:   9/14/92°dONLNdlg<s¢* Last reviewed: 7/2/93°dONLNdÇ<ã‹*The LaserWriter driver before °dONLNd†‹ã˛)†2the QuickDraw GX version has an option to print in°dONLNd”ã<óØ(≥ZIColor/Grayscale or Black & White. Why isn’t this option in the QuickDraw °dONLNdãØó˛(≥ÕGX LaserWriter°dONLNd+ó<£](øZdriver?°dONLNd3£<ØN* ___°dONLNd7ª<«ß*The Color/Grayscale °dONLNdKªß«˛)kAoption was added to the LaserWriter driver only for compatibility°dONLNdç«<”k(ÔZ?reasons. At the time, some applications couldn’t deal with the °dONLNdëk”˛(Ôâcolor option (specifically with°dONLNdÏ”<fli(˚Z<cGrafPorts), so a Black & White mode was also provided. The °dONLNd(”ifl˛(˚áBlack & White mode exhibited°dONLNdEfl<ÎR(Z=the same functionality as the earlier LaserWriter driver 5.2.°dONLNdɘ<N*4Because most applications are color compatible now, °dONLNd∑˜N˛(lthe option was removed from the°dONLNd◊<¨(+ZLQuickDraw GX printer drivers. Some people reported that the option let them °dONLNd#¨˛(+ print faster when°dONLNd5<b(7Z:they chose Black & White. This was true because of quirks °dONLNdob˛(7Ä!in the earlier LaserWriter driver°dONLNdë<'º(CZPversion. Under QuickDraw GX, this shouldn’t be a problem. If it turns out to be °dONLNd·º'˛(C⁄
  6630. a problem for°dONLNdÔ'<3ê(OZFyour driver, you could incorporate black-and-white threshold printing °dONLNd5'ê3˛(OÆinto your “rough draft°dONLNdL3<?¢([ZGmode” code. The QuickDraw GX LaserWriter driver always prints in color. ¡X¡
  6631. *{#PR 525 - QuickDraw GX Printing Q&As(÷3) of 3(ÏZM.PR.QDGXprt.Q&Asˇ